2

First of all, this isn't for a keylogger, it's for an input in a roguelike game where the JLabel in my JFrame will say "Name: " and I want to be able to type A-Za-z. After having a look at lots of options for key input, I am back where I started using KeyStrokes and Actions.

What I am wondering is whether there is a way to add a range of keys, rather than repeating this 56 times:

Action a = new AbstractAction() {

    public void actionPerformed(ActionEvent e) {
        // add a to string
    }
};
getInputMap().put(KeyStroke.getKeyStroke("a"), "a");
getActionMap().put("a", a);

I mean, I could do it this way, just write a bit of copy and pasting, but I really do hate that. There has to be a more elegant solution than using KeyListener which isn't very good as it means I have to somehow have focus but my window is simply one JFrame with a big JLabel in it.

Also, I've only been doing java a few days now, so that's why I am probably missing the a very commonly known solution, but if there is one, please do share! Appreciated.

Mot
  • 28,248
  • 23
  • 84
  • 121
Adam K Dean
  • 7,387
  • 10
  • 47
  • 68
  • 2
    Why not simply using a `JTextField` to capture input ? – Robin Jul 03 '12 at 10:02
  • I looked at this but it needs to be focused, and would need to be hidden, and I would like to use events, so that I can update the UI a key at a time. – Adam K Dean Jul 03 '12 at 10:05
  • Just curious, what should happen when the user pressed A-Za-z keys? Maybe you have a more general usability problem here? – Mot Jul 03 '12 at 10:07
  • 1
    Try [attaching](http://docs.oracle.com/javase/7/docs/api/java/awt/Component.html#addKeyListener(java.awt.event.KeyListener)) a [`KeyListener`](http://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyListener.html) to a suitably top-level `Component`. – millimoose Jul 03 '12 at 10:07
  • @MikeL.: In a roguelike game, the usual approach for the game to manage the whole UI in a huge rectangle of text and ASCII graphics. It makes sense for the engine to capture most keyboard input at the top level and process it on its own. I don't see a usability problem here. – millimoose Jul 03 '12 at 10:09
  • @MikeL. I probably do, new to java, trying to work out the best way to implement restricted input. If there is a way of getting all keyboard input whilst the window is active via a `KeyListener` for example, then that would be best, but so far I can't get `KeyListener` to work, I think it needs focus? – Adam K Dean Jul 03 '12 at 10:09
  • @AdamKDean: Hm. Wild guess #2: use a [KeyEventDispatcher](http://docs.oracle.com/javase/7/docs/api/java/awt/KeyEventDispatcher.html). Seems that's how you can override key events only being sent to focused elements. – millimoose Jul 03 '12 at 10:14
  • Hmm, adding the KeyListener to the JFrame seems to work. I was adding it to the content pane before, which didn't. I think this may work. Thanks @millimoose! – Adam K Dean Jul 03 '12 at 10:14

2 Answers2

1

This is a solution:

for (char c = 'a'; c <= 'z'; c++) {
    String ks = String.valueOf(c);
    getInputMap().put(KeyStroke.getKeyStroke(ks), ks);
    getActionMap().put(ks, a);
    ks = ks.toUpperCase();
    getInputMap().put(KeyStroke.getKeyStroke(ks), ks);
    getActionMap().put(ks, a);
}

but I think you should prefer a JTextField with DocumentListener.

Alberto
  • 1,569
  • 1
  • 22
  • 41
0

I am using a content manager class which treats each "screen" as a JPanel which is set as the content pane, I put a reference to the parent JFrame into the base "screen" class and then added a KeyListener to the parent JFrame. This captures input just how I want it to. I didn't do this before as I mistakenly added the KeyListener to the content pane. It all appears to work fine now.

public void run() {
    this.getParent().addKeyListener(new KeyListener() {

        public void keyPressed(KeyEvent e) {
            appendLabel(e.getKeyChar());
        }

        public void keyReleased(KeyEvent e) { }
        public void keyTyped(KeyEvent e) { }
    });
}

Thanks @millimoose!

Adam K Dean
  • 7,387
  • 10
  • 47
  • 68