2012-12-15 194 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