第一次打开 JDialog 时运行 KeyEventDispacther,然后将其删除

Lui*_*SSB 4 java swing keyevent jdialog keyboard-events

我正在做一个应用程序,它必须通过键盘读取一些字符并解释它们。

为了捕获键,我打开了一个 JDialog 并设置了一个 KeyEventDispatcher,这样我就可以在 dispatchKeyEvent 方法中捕获字符。在 JDialog 中,有一个按钮可以删除 KeyEventDispatcher 并处理 JDialog。

它有两个问题:
- 第一次打开 JDialog,就像没有设置 KeyEventDispatcher
- 当我关闭并打开这个 JDialog 时,KeyEventDispatchers 正在累积(第一次打开,没有运行;第二次打开,有一个正在运行,第 3 次打开,有 2 个正在运行,...)

似乎 KeyEventDispacthers 是在 JDialog 关闭但未删除时设置的,而不是在 JDialog 打开时设置并在关闭时删除。

有人可以帮助我了解发生了什么以及我该如何解决?

这是 JDialog 类的简化版本(只有关键捕获部分):

public class SequenceDialog {
    private JDialog dialog;
    private JButton finishButton;
    private DialogKeyEventDispatcher keyEventDispatcher;

    public SequenceDialog() {
        initializeDialog();
    }

    private void initializeDialog() {
        dialog = new JDialog();
        finishButton = new JButton("Finish");

        finishButton.addActionListener(new FinishButtonListener());
        dialog.setModalityType(ModalityType.APPLICATION_MODAL);
        dialog.add(finishButton);
        setKeyListener();
        dialog.setVisible(true);
        dialog.pack();
    }

    /** Adds the KeyEventDispacther */
    private void setKeyListener() {
        keyEventDispatcher = new DialogKeyEventDispatcher();

        KeyboardFocusManager manager = KeyboardFocusManager
                .getCurrentKeyboardFocusManager();
            manager.addKeyEventDispatcher(keyEventDispatcher);
    }

    private class FinishButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            //Removing the KeyEventDispacther
            KeyboardFocusManager manager = KeyboardFocusManager
                    .getCurrentKeyboardFocusManager();
                manager.removeKeyEventDispatcher(keyEventDispatcher);

            dialog.dispose();
        }
    }

    /** The KeyEventDispatcher to be executed */
    private class DialogKeyEventDispatcher implements KeyEventDispatcher {
        public boolean dispatchKeyEvent(KeyEvent e) {
            if(e.getID() == KeyEvent.KEY_PRESSED) {
                System.out.println(KeyEvent.getKeyText(e.getKeyCode()));
            }

            return false;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果有另一种捕获密钥的方法,我很乐意看到它。到目前为止,我已经尝试过:

  • KeyListener,即使我将它添加到 JButton 和 contentPane 也不起作用
  • KeyEventPostProcessor,与使用 KeyEventDispatcher 的效果相同
  • KeyBinding,不起作用,似乎不是最佳选择,因为我必须捕获输入的所有内容

kle*_*tra 5

无法重现不工作的第一次。

可以重现堆叠:通过单击标题中的关闭图标关闭对话框时不会删除调度程序。在这种情况下,在关闭对话框后打印在主框架中键入的笔画。

在 dispose 和 WindowListener 中(而不是在完成操作中),可以通过 so 可靠地删除调度程序:

    private void initializeDialog() {
        dialog = new JDialog() {

            @Override
            public void dispose() {
                KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
                manager.removeKeyEventDispatcher(keyEventDispatcher);
                LOG.info("disposed: " + manager);
                super.dispose();
            }

        };
        WindowListener l = new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
                manager.removeKeyEventDispatcher(keyEventDispatcher);
                LOG.info("closing: " + manager);
            }

        };
        dialog.addWindowListener(l);
Run Code Online (Sandbox Code Playgroud)