为什么键绑定不能与CardLayout一起使用?

时间:2019-01-23 18:43:38

标签: java swing key-bindings

在我的问题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”,但只有在我不按下按钮的情况下,它才会执行

2 个答案:

答案 0 :(得分:1)

键绑定并不是特别复杂,但是它们可能需要一点时间来适应。为此,手头准备好How to Use Key BindingsJavaDocs for JComponent作为参考。

按键绑定API的目标之一是可配置性,它使我们可以更好地控制确定按键何时触发事件。

JComponent#getInputMap方法返回一个映射,该映射绑定到“焦点对准时”上下文。这意味着在触发绑定之前,组件将需要具有焦点(并且显然应该是可聚焦的)。

如果要在不同级别触发绑定,则需要使用JComponent#getInputMap(int)并将其传递给三个可用上下文之一:

您使用哪种方式取决于您的需求,但是我通常很懒,当我想要“全局”状态时,请选择JComponent.WHEN_IN_FOCUSED_WINDOW

答案 1 :(得分:-1)

对我有用的解决方案:我只是在button.addActionListener lambda上添加了一条语句,将重点放在mainPanelmainPanel.grabFocus();上。

完整的代码如下所示:

button.addActionListener(e -> {
    status = status.equals("Menu") ? "World" : "Menu";

    layout.show(mainPanel, status);
    button.setText("Exit " + status);
    mainPanel.grabFocus();
});