调度 KeyEvent(或任何类型的事件?)时不会通知侦听器

Posted

技术标签:

【中文标题】调度 KeyEvent(或任何类型的事件?)时不会通知侦听器【英文标题】:Listener won't be notified when dispatch-ing a KeyEvent (or any kind of event?) 【发布时间】:2021-09-17 00:07:16 【问题描述】:

这不是针对特定关键事件的问题。我以 KeyEvents/KeyListeners 和 JButton 为例。我想要的只是能够方便地在 JUnit 测试中触发侦听器。

我试图在单元测试中触发一个关键的侦听器,但由于某种原因该侦听器没有被触发。

 public class Example 
    public static void main(String[] args) 
        AtomicBoolean keyReleasedRan = new AtomicBoolean(false);
        JButton button = new JButton();
        button.addKeyListener(new KeyAdapter() 
            @Override
            public void keyReleased(KeyEvent e) 
                keyReleasedRan.set(true);
            
        );

        int modifiers = 100; //Something, we don't care
        int keyCode = KeyEvent.VK_A; //something realistic
        KeyEvent event = new KeyEvent(button, KeyEvent.KEY_RELEASED, System.currentTimeMillis() + 200,
                modifiers, keyCode, 'a');

        button.dispatchEvent(event);

        System.out.println("KEY RELEASED RAN: " + keyReleasedRan.get());
    

我已经在事件构造函数中尝试了多个参数,以防它起作用,但监听器仍然没有被触发。

唯一可行但我真的不想遵循的方法是遍历 KeyListener(s) 并为每个侦听器调用 keyReleased() 方法。

知道我做错了什么吗?

我尝试了其他组件而不是 JButton,但结果相同。

【问题讨论】:

1) 对于 Swing,我们通常使用 key bindings 而不是较低级别的 KeyListener。 2)为了尽快获得更好的帮助,edit添加minimal reproducible example或Short, Self Contained, Correct Example。 @AndrewThompson 不,不。这与具体的关键事件无关。这是关于任何类型的事件。我想通过 JUnit 测试来触发听众。我知道键绑定。 KeyEvent/KeyListener 只是一个例子。关于 SSCCE,我补充说。我认为 JUnit 测试用例也被认为是某种最小示例,但无论如何。 如果您将按钮放在 JFrame 中,请激活 JFrame 并调用按钮上的事件 @Ofek 激活框架表示frame.setVisible(true)? 试试 button.doClick(0); 【参考方案1】:

正如 cmets 所说,如果将它附加到 JFrame,它就可以工作。

当您在单元测试中使用它时,您还希望自动关闭 JFrame。 所以我添加了frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));

public class Test 
    public static void main(String[] args) 
        JButton button = new JButton("Run");
        button.addKeyListener(new KeyAdapter() 
            @Override
            public void keyReleased(KeyEvent e) 
                System.out.println("runs...");
            
        );
        
        JFrame frame = new JFrame();
        frame.add(button);
        frame.setSize(50, 50);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    
    
        int modifiers = InputEvent.SHIFT_DOWN_MASK; //Something, we don't care
        int keyCode = KeyEvent.VK_A; //something realistic
        KeyEvent event = new KeyEvent(button, KeyEvent.KEY_RELEASED, System.currentTimeMillis() + 200,
            modifiers, keyCode, 'a');
    
        button.dispatchEvent(event);
        frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
    

【讨论】:

frame.setVisible(true) 不是单元测试的选项。实际上,构建JFrame 不是测试的选项。只是因为它很贵。

以上是关于调度 KeyEvent(或任何类型的事件?)时不会通知侦听器的主要内容,如果未能解决你的问题,请参考以下文章

Adobe Air 文件运行时权限拒绝不会调度事件

安卓onKeyDown事件 重新获取焦点

Redis 事件通知(keyspace & keyevent notification)

什么触发(或生成)KeyEvent.ACTION_MULTIPLE?

从 QML 生成 KeyEvent

操作系统学习笔记