在我的问题How do I draw on a JPanel from multiple outside classes?中,Frakcool给了我有关使用键绑定的建议,但没有任何效果:当JButton在框架的前面放置另一个JPanel时,键绑定没有响应。这是代码:
private JFrame frame;
private JPanel[] statePanels;
private CardLayout layout;
private JPanel mainPanel;
private JButton button;
private String status;
void initAndShow()
{
//Init stuff
mainPanel = new JPanel(layout);
statePanels = new JPanel[2];
button = new JButton("Exit");
status = "Menu";
button.addActionListener(e -> {
status = status.equals("Menu") ? "World" : "Menu";
layout.show(mainPanel, status);
});
statePanels[0] = new OutWorldHandler();
statePanels[1] = new InWorldHandler();
mainPanel.add(statePanels[0], "Menu");
mainPanel.add(statePanels[1], "World");
mainPanel.getInputMap().put(KeyStroke.getKeyStroke('f'), "close");
mainPanel.getActionMap().put("close", this);
frame.add(mainPanel);
frame.add(button, BorderLayout.SOUTH);
}
@Override
public void actionPerformed(ActionEvent e)
{
System.out.println("hi");
}
预期的输出是,当我一直按下f
时,控制台将打印出“ hi”,但只有在我不按下按钮的情况下,它才会执行
答案 0 :(得分:1)
键绑定并不是特别复杂,但是它们可能需要一点时间来适应。为此,手头准备好How to Use Key Bindings和JavaDocs for JComponent
作为参考。
按键绑定API的目标之一是可配置性,它使我们可以更好地控制确定按键何时触发事件。
JComponent#getInputMap
方法返回一个映射,该映射绑定到“焦点对准时”上下文。这意味着在触发绑定之前,组件将需要具有焦点(并且显然应该是可聚焦的)。
如果要在不同级别触发绑定,则需要使用JComponent#getInputMap(int)
并将其传递给三个可用上下文之一:
JComponent.WHEN_IN_FOCUSED_WINDOW
JComponent.WHEN_FOCUSED
JComponent. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
您使用哪种方式取决于您的需求,但是我通常很懒,当我想要“全局”状态时,请选择JComponent.WHEN_IN_FOCUSED_WINDOW
答案 1 :(得分:-1)
对我有用的解决方案:我只是在button.addActionListener
lambda上添加了一条语句,将重点放在mainPanel
:mainPanel.grabFocus();
上。
完整的代码如下所示:
button.addActionListener(e -> {
status = status.equals("Menu") ? "World" : "Menu";
layout.show(mainPanel, status);
button.setText("Exit " + status);
mainPanel.grabFocus();
});