Java: need to get input line while in a GUI, is only working in console

2.3k views Asked by At

My friends and I have written a program in Java with a GUI, made for touchscreen terminals with no keyboard/mouse. Everything occurs within the GUI, and most of the input is button presses. We want to attach a magnetic card reader (in keyboard mode) and read from a card, then perform processing based on the data from it.

I wrote a class that works in the console, but when run through the GUI it just hangs until I alt+tab and click inside the IDE's (Eclipse's) console and swipe the card. What I'm looking for is a way to get this input w/o having to leave the GUI.

The MCR works as if you simply typed the card info on a keyboard-- it'll send a line containing both tracks of data anywhere you could type the same line, txt document, console, whatever.

The relevant code is as follows:

import java.util.Scanner;

public class CardRead {
    public static void main() 
    {
    String raw_card_data = "";

    Scanner read = new Scanner( System.in );
    System.out.println("Scan card"); // changed to an outputArea.setText for GUI

    raw_card_data = read.nextLine(); // works in console, not within GUI

    /* insert processing here */
    }
}    

in the GUI, the code is simply:

cardreadbtn.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent e)
        {
            CardRead.main();
        }
    }); 

I thought maybe an InputStream would work, but I've never really worked with them. I googled and found this thread : I tried integrating the suggestion about IOUtils, as follows:

InputStream is = System.in;
StringWriter writer = new StringWriter();
IOUtils.copy(is, writer, null);
raw_card_data = writer.toString();
System.out.println(raw_card_data);
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(writer);

I don't know if I'm doing that right, but in the console (haven't tried in the GUI), it now says "Scan Card" and never progresses to print out raw_card_data or do anything else. "closeQuietly" I got from here:

...but again, I dunno if I'm doing it right. Never worked with apache IOUtils either.

So I'm stuck, and I'm looking to you guys. How can I grab this card data w/o leaving the GUI to do so?

Important note: The card data has a variable # of spaces in it (which we need to preserve), so anything like Scanner.next() won't work. The card reader is set up to send a line with both tracks separated by delimiters and then a carriage return, so .nextLine() works. The card data is also a variable # of bytes/characters.

Also: In the first code block, the System.out.println is before a do while loop that raw_card_data = read.nextLine() is actually in (I left it out because I felt it's not relevant, but now I'm curious why it's doing this). When the println is changed to a setText() to display to a JTextArea in the GUI, it doesn't display until AFTER the card data is input in the console, even though it occurs before the do while and should execute before it. I don't understand, lol.

2

There are 2 answers

1
aoi222 On BEST ANSWER

From what I read, Java does not natively allow you to directly monitor the keyboard for input except on the focused Window. I can see two ways that you may be able to solve your problem. The first is by adding a simple key listener to your application and then just streaming the input and processing it. The second is to use a low level keyboard hook.

There was a previous discussion with someone trying to do something similar here: Can Java see activity of my keyboard?

and from there I was able to get to this article with a low level hook implementation: http://ksquared.de/blog/2011/07/java-global-system-hook/

3
Pedantic On

I wrote a class that works in the console, but when run through the GUI it just hangs until I alt+tab and click inside the IDE's (Eclipse's) console and swipe the card.

This makes me suspect you're running the code inside of Eclipse. When you 'test' code from inside the IDE, Eclipse basically emulates the console, which is why you have to use the console view in the IDE.

When you run the application normally (ie, not from within the IDE), a real console should remain open behind the UI. I haven't personally tested reading from the console when running a Swing app, but it should work.