java swing key bindings - missing action for released key

Зарегистрировав привязки клавиш "SPACE" и "released SPACE", которые работают как рекламируется, когда пробел является единственной нажатой/отпущенной клавишей, я заметил, что нажатие пробела, затем нажатие ctrl (или любой другой клавиши-модификатора), затем отпускание пробела и, наконец, отпускание ctrl приведет к выполнению действия, связанного с "SPACE", но не действия, связанного с "released SPACE".

Каков предпочтительный способ вызвать выполнение действия, когда пробел больше не нажат (или одновременно нажата клавиша-модификатор)? Я пробовал это только на Windows 7, 64-разрядной версии.

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.AbstractAction;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
import java.awt.Cursor;

class Bind extends JPanel {
  {
    getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressed");
    getInputMap().put(KeyStroke.getKeyStroke("released SPACE"), "released");
    getActionMap().put("pressed", new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        System.out.println("pressed");
        setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); 
      }
    });
    getActionMap().put("released", new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        System.out.println("released");
        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
      }
    });
  }
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override public void run() {
        JFrame f = new JFrame("Key Bindings");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        f.add(new Bind());
        f.setSize(640, 480);
        f.setVisible(true);
      }
    });
  }
}

UPDATE: Вот способ избежать залипания пробела при случайном нажатии ctrl, alt или shift перед тем, как отпустить пробел:

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.AbstractAction;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
import java.awt.Cursor;

class Bind extends JPanel {
  {
    getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressed");
    getInputMap().put(KeyStroke.getKeyStroke("released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("ctrl released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("shift released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("shift ctrl released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("alt released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("alt ctrl released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("alt shift released SPACE"), "released");
    getInputMap().put(KeyStroke.getKeyStroke("alt shift ctrl released SPACE"), "released");
    getActionMap().put("pressed", new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        System.out.println("pressed");
        setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); 
      }
    });
    getActionMap().put("released", new AbstractAction() {
      @Override public void actionPerformed(ActionEvent e) {
        System.out.println("released");
        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
      }
    });
  }
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override public void run() {
        JFrame f = new JFrame("Key Bindings");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        f.add(new Bind());
        f.setSize(640, 480);
        f.setVisible(true);
      }
    });
  }
}
10
задан Aksel 16 December 2011 в 09:22
поделиться