javauser-interfaceinputjava.util.scannermagnetic-cards

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


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.


Solution

  • 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/