Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

key binding won't work with alt-up and alt-left arrow combined

843806Jul 27 2009 — edited Jul 27 2009
I was playing with key binding trying to create a small app where a timer is started with the press of an alt-arrow key and stopped when the key is released. The timers append Strings to a JTextArea telling which alt-arrow key is currently pressed.

This program works, and in fact if you press a combination of any two keys, both timers will work simultaneously, that is unless you press both up arrow and left arrow together. Can anyone see a bug in the program that explains why it won't work for these two particular keys when combined? Thanks in advance, Pete

My SSCCE,
KeyBindingEg.java
package javaforum2009;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import javax.swing.*;

public class KeyBindingEg {
  
  // parallel arrays -- sorry
  private static final int[] ARROW_KEYS = { 
      KeyEvent.VK_UP, KeyEvent.VK_DOWN,
      KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT };
  private static final String[] ACTION_STRINGS = { 
    "Up", "Down", 
    "Left", "Right" };
  private static final String PRESSED = "PRESSED";
  private static final String RELEASED = "RELEASED";
  private static final int TIMER_DELAY = 100;

  private JPanel mainPanel = new JPanel();
  private JTextArea textArea = new JTextArea(20, 30);

  public KeyBindingEg() {
    JPanel northPanel = new JPanel(); 
    northPanel.add(new JLabel("This JTextField has the focus: "));
    northPanel.add(new JTextField(10));
    
    textArea.setEditable(false);

    mainPanel.setLayout(new BorderLayout());
    mainPanel.add(northPanel, BorderLayout.NORTH);
    mainPanel.add(new JScrollPane(textArea), BorderLayout.CENTER);

    setBindings();
  }

  private void setBindings() {
    int context = JComponent.WHEN_IN_FOCUSED_WINDOW;
    InputMap inputMap = mainPanel.getInputMap(context);
    ActionMap actionMap = mainPanel.getActionMap();
    for (int i = 0; i < ARROW_KEYS.length; i++) {
      // timer is started on key press and stopped
      // on key release.
      Timer timer = new Timer(TIMER_DELAY, new KeyTimerListener(
          ACTION_STRINGS));
timer.setInitialDelay(0);

// get input maps for all alt-arrow keys for both key press
// and key release
inputMap.put(KeyStroke.getKeyStroke(ARROW_KEYS[i],
InputEvent.ALT_DOWN_MASK, false), ACTION_STRINGS[i] + PRESSED);
inputMap.put(KeyStroke.getKeyStroke(ARROW_KEYS[i],
InputEvent.ALT_DOWN_MASK, true), ACTION_STRINGS[i] + RELEASED);

// set corresponding actions for the two different key presses above
actionMap.put(ACTION_STRINGS[i] + PRESSED, new ArrowKeyAction(false, timer));
actionMap.put(ACTION_STRINGS[i] + RELEASED, new ArrowKeyAction(true, timer));
}
}

@SuppressWarnings("serial")
private class ArrowKeyAction extends AbstractAction {
private boolean onKeyRelease;
private Timer swingTimer;

public ArrowKeyAction(boolean onKeyRelease, Timer swingTimer) {
this.onKeyRelease = onKeyRelease;
this.swingTimer = swingTimer;
}

public void actionPerformed(ActionEvent arg0) {
if (onKeyRelease) {
swingTimer.stop();
} else {
swingTimer.start();
}
}
}

private class KeyTimerListener implements ActionListener {
private String actionString;

public KeyTimerListener(String actionString) {
this.actionString = actionString;
}

public void actionPerformed(ActionEvent arg0) {
textArea.append(actionString + " pressed\n");
}
}

public JComponent getPanel() {
return mainPanel;
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("KeyBindings Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new KeyBindingEg().getPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Aug 24 2009
Added on Jul 27 2009
3 comments
106 views