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

发布于 2024-12-28 13:41:02 字数 2410 浏览 4 评论 0原文

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

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

它有两个问题:
- 第一次打开JDialog时,就像没有设置KeyEventDispatcher
- 当我关闭并打开这个 JDialog 时,KeyEventDispatcher 正在累积(第一次打开,没有一个正在运行;第二次打开,有一个正在运行,第三次打开,有 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;
        }
    }
}

如果有另一种捕获按键的方法,我会很高兴看到它。到目前为止,我尝试过的:

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

I'm doing an application that must read some characters via keyboard and interpret them.

To capture the keys, I open a JDialog and set a KeyEventDispatcher, so I can capture the characters in the dispatchKeyEvent method. In the JDialog there's a button that removes the KeyEventDispatcher and disposes of the JDialog.

There are two problems with it:
- The first time the JDialog is opened, it's like the KeyEventDispatcher was not set
- As I close and open this JDialog, the KeyEventDispatchers are cumulating (open he 1st time, there's none running; open the 2nd time, there's one running, open the 3rd time, there're 2 running, ...)

It seems that the KeyEventDispacthers are being set when the JDialog is closed and not removed, instead of being set when the JDialog is opened and removed when it closes.

Someneone could please help me understand what's happening and how I can fix it?

Here's a simplified version of the JDialog class (with only the key capture part):

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;
        }
    }
}

If there's another way of capturing the keys, I will gladly see it. So far, what I have tried:

  • KeyListener, didn't work even when I added it to the JButton and the contentPane
  • KeyEventPostProcessor, had the same effect as using KeyEventDispatcher
  • KeyBinding, didn't work and doesn't seem like the best choice, as I must capture everything typed

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

后eg是否自 2025-01-04 13:41:02

无法重现首先不工作的情况。

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

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

    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);

Can't reproduce the not-working on first.

Can reproduce the stacking: the dispatcher is not removed when closing the dialog by clicking on the close icon in the title. In this case, strokes typed in the main frame are printed after the dialog has been closed.

The dispatcher can be reliably removed by so in both dispose and a WindowListener (instead of in the finish action):

    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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文