【问题标题】:How do I handle several KeyStrokes in the same actionPerformed method of an Action Listener in Java Swing?如何在 Java Swing 中的 Action Listener 的同一 actionPerformed 方法中处理多个 KeyStroke?
【发布时间】:2020-03-02 17:54:55
【问题描述】:

在了解了如何处理窗口级键事件 (How to get a Key Event in a Java Swing JFrame instance which has many JTextFields?) 之后,我想定义一个可以通过以下方式附加的类:

frame.getRootPane ().registerKeyboardAction ( ... );

该类包含在下面,它打算在主窗口和所有子窗口中使用。这个想法是,无论您是在主窗口中还是在其中一个子窗口中,Fx 键都将单独显示/隐藏子窗口(即,所有应用程序都将以相同的方式响应 Fx 键击)。构造函数包括当前窗口和包含所有窗口的主窗口。

我的问题是我不知道如何识别在方法actionPerformed 中按下了哪个键。 欢迎任何关于如何识别哪个KeyStroke.getKeyStroke(KeyEvent.VK_Fxx,0) 触发了 actionPerformed 的提示。

public class ApplicationLevelKeys implements ActionListener {

    private MainWindow mainWindow;

    public ApplicationLevelKeys(JFrame frame, MainWindow mw) {
        mainWindow = mw;
        frame.getRootPane().registerKeyboardAction(this, KeyStroke.getKeyStroke(KeyEvent.VK_F2,0), JComponent.WHEN_IN_FOCUSED_WINDOW);
        frame.getRootPane().registerKeyboardAction(this, KeyStroke.getKeyStroke(KeyEvent.VK_F12,0), JComponent.WHEN_IN_FOCUSED_WINDOW);
    }

    @Override
    public void actionPerformed(final ActionEvent e) {

        // F12 - Display Attribute Window
        System.out.println("F12");
        if(mainWindow.propertiesWindow.isVisible()) {
            mainWindow.propertiesWindow.setVisible(false);
        } else {
            mainWindow.propertiesWindow.setVisible(true);
        }

        // F2 - Display Period Window
        System.out.println("F2");
        if(mainWindowperiodWindow.isVisible()) {
            mainWindow.periodWindow.setVisible(false);
        } else {
            mainWindow.periodWindow.setVisible(true);
        }


    }

}

【问题讨论】:

  • (1-) frame.getRootPane ().registerKeyboardAction ( ... ); - 您没有阅读您不应该使用该方法的评论吗?此外,您应该使用 Action,而不是 ActionListener。当您只是复制发布的代码而不是实际阅读教程链接时,这就是问题所在。顺便说一句,您无法处理多个 KeyStroke 键绑定是将 KeyStroke 映射到 Action。

标签: java swing actionlistener keystroke actionevent


【解决方案1】:

我刚刚浏览了一些项目,发现了一个示例,其中我使用了 InputMapActionMap 来存储 KeyStrokes 及其相应的操作;

private void initKeyBindings(final JComponent c)
    {
        final InputMap iMap = c.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        final ActionMap aMap = c.getActionMap();
        String key;
        key = "f1";
        iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0), key);
        aMap.put(key, showHelpAction);

        key = "f2";
        iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), key);
        aMap.put(key, saveTableAction);

        key = "f5";
        iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0), key);
        aMap.put(key, loadTableAction);

        key = "f6";
        iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F6, 0), key);
        aMap.put(key, focusDefaultCommandsAction);

        key = "f7";
        iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0), key);
        aMap.put(key, focusProtocolCommandsAction);

        key = "f11";
        iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0), key);
        aMap.put(key, loadDokuFilesAction);

        key = "f12";
        iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F12, 0), key);
        aMap.put(key, startSignalplanAction);

        key = "Ctrl+R";
        iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK), key);
        aMap.put(key, openRevisorAction);

    }

在您的actionPerformed() 方法中,您现在可以遍历aMap 并将aMap.getKey() 与您按下的键进行比较,然后通过aMap.getValue() 触发相应的操作/方法。

【讨论】:

  • 如果我尝试这样做,对于放入 aMap 中的方法,我会收到错误“找不到符号”。您能否展示其中一种方法的示例(即 showHelpAction)?
  • 你到底在哪里得到这个错误?而且我认为我对这个解决方案的想法是错误的。这个想法是您将要添加这些绑定的组件(在我的情况下是 JMenu)作为参数传递,并且此方法可以完成所有需要完成的工作。因此,在组件上调用此方法后,F1 键现在将触发 showHelpAction。关于您的请求,在 showHelpAction 中除了 actionPerformed() 调用另一个方法之外没有其他任何事情发生,但不需要进一步的事件处理。
  • 我意识到这并不完全符合您的要求,因为这不是您要求的“在一个 actionPerformed 方法中处理多个 KeyStrokes”,但它仍然可能是一种可行的替代方案。我想使用这个变体不需要你在单个 actionPerformed 中处理不同的案例,而是需要你为每个案例创建一个 Action。至少在我看来,这听起来像是更简洁的代码,但它可能不是您想要的,抱歉。
  • 我刚刚发现了 6 年前的 this SO 线程,它讨论了使用 Input/Action-Map 与使用 registerKeyboardAction。您使用的后一个别名似乎已经过时了很长一段时间。所以也许重写这段代码以适应最现代的方法是一个好主意。
  • 我设法理解了它(它实际上是一个很好的解决方法,它在不同的 AbstractActions 中实现操作)。我收到错误是因为我没有完全理解代码(现在我明白了)。我面临的问题是,我从窗口管理器(我在 Linux 中使用 MWM)得到了一个奇怪的行为,其中在子窗口中切换可见性一直有效,直到某个时刻焦点设置到不同的窗口。我不知道为什么会发生这种情况,但我将使用不同的方法来避免这种行为。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-09
  • 2023-03-27
相关资源
最近更新 更多