2012-12-15 52 views
1

我有JButton通过ActionListener执行某些操作。在我尝试使用动作绑定键盘快捷键(在this之后)后,鼠标点击按钮可以工作,但对键盘没有反应。键绑定不起作用

代码之前

在面板中创建的按钮,添加了actionListener。

private FooActionListener actionListener = new FooActionListener(); 

buttonLeft = new JButton("Left"); 
up.addActionListener(actionListener); 

然后,主类外FooActionListener类中的actionPerformed方法:

public void actionPerformed(ActionEvent e) { 
    Object source = e.getSource(); 
    if (source == buttonLeft) { thing.move(Direction.LEFT); } 
} 

代码后

final String leftText = "Left"; 
final Action left = new AbstractAction() { 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     thing.move(Direction.LEFT); 
    } 
}; 

buttonLeft = new JButton(left); 
buttonLeft.setText(leftText); 
KeyStroke keyLeft = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0); 
buttonLeft.getInputMap(buttonLeft.WHEN_IN_FOCUSED_WINDOW).put(keyLeft, 
    "Left"); 
buttonLeft.getActionMap().put("Left", left); 

更新:我不太清楚新的代码实际上执行它应该是鼠标。假设对象应该通过一次点击来移动25个像素,并且它在原始代码中执行。但是随着新动作的出现,它似乎会在每次点击时移动两次甚至三次,这表明动作有些奇怪的行为。

回答

2

按钮吸引你的映射是可能的,但是,我会做的稍微有点不同。

因为您已经使用了Action(正确),所以您的移动逻辑已经大部分已经集中。

我只是简单地将映射应用到主容器。

public class TestKeybindings01 { 

    public static void main(String[] args) { 
     new TestKeybindings01(); 
    } 

    public TestKeybindings01() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private JLabel label; 
     private JButton left; 
     private JButton right; 

     public TestPane() { 

      label = new JLabel("Make a choice"); 
      label.setHorizontalAlignment(JLabel.CENTER); 

      LeftAction leftAction = new LeftAction(label); 
      RightAction rightAction = new RightAction(label); 

      InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); 
      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "left"); 
      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "right"); 

      ActionMap am = getActionMap(); 
      am.put("left", leftAction); 
      am.put("right", rightAction); 

      left = new JButton(leftAction); 
      right = new JButton(rightAction); 

      setLayout(new GridBagLayout()); 
      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.gridx = 0; 
      gbc.gridy = 0; 
      gbc.gridwidth = 2; 
      gbc.anchor = GridBagConstraints.CENTER; 
      gbc.fill = GridBagConstraints.HORIZONTAL; 
      add(label, gbc); 

      gbc.gridy++; 
      gbc.gridwidth = 1; 
      add(left, gbc); 
      gbc.gridx++; 
      add(right, gbc); 


     } 

    } 

    public abstract class AbstractDirectionAction extends AbstractAction { 

     private JLabel label; 

     public AbstractDirectionAction(JLabel label) { 
      this.label = label; 
     } 

     public JLabel getLabel() { 
      return label; 
     } 

     public void setDirection(String text) { 
      getLabel().setText(text); 
     } 

    } 

    public class LeftAction extends AbstractDirectionAction { 

     public LeftAction(JLabel label) { 
      super(label); 
      putValue(NAME, "<<"); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      setDirection("Left"); 
     } 

    } 

    public class RightAction extends AbstractDirectionAction { 

     public RightAction(JLabel label) { 
      super(label); 
      putValue(NAME, ">>"); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      setDirection("Right"); 
     } 

    } 

} 
+0

请您详细说明吸收映射的含义是什么?此外,检查问题的更新,看看是否提示任何事情。这个EventQueue.invokeLater业务是关于什么的? – theUg

+0

按钮实现可能“吸收”了关键事件,这可能是其对助记符支持的一部分,可能会阻止它为关键绑定引发事件。我可以考虑这样一个重复事件的唯一原因是,你正在关键。 'EventQueue.invokeLater'是因为Swing是一个单线程API,所有对UI的更新都必须在Event Dispatching Thread中进行。当你执行'main'时,确保你没有使用EDT – MadProgrammer

+0

至于重复,我在这里谈论鼠标点击。我使用与原始代码完全相同的鼠标点击,但它似乎像它在相同的点击两次调用thing.move方法。有没有一种方法来调试它? – theUg