将KeyEvents分派给未聚焦的组件

时间:2015-03-25 13:40:12

标签: java swing events awt keyboardfocusmanager

以下是该方案: 我有两个java应用程序。第一个是使用swing GUI的可视化应用程序,所有这些都包含在JFrame中,JFrame具有非常复杂的行为(非常古老的代码库),我无法更改。我只是有一个JFrame对象的钩子。

第二个应用程序是我正在编写的应用程序,它基本上是第一个应用程序的单元测试程序。使用JFrame钩子和JDI,我已经能够进行所有需要执行这些测试的内省,这些测试非常顺利。事实上,我的测试进展顺利,我想在后台运行它们。但是,由于我的许多测试涉及将KeyEvents和MouseEvent分派给JFrame,因此一旦窗口失去焦点,这些将停止。根据我的阅读,这似乎是由于默认的KeyboardFocusManager的要求,它只会将这些事件发送到既显示又聚焦的组件(这也需要包含它们的窗口同时显示和聚焦)。这让我想到了我的问题:

如果没有KeyboardFocusManager停止游行,我如何“强制”调度事件到某些挥动组件?

重要说明:我希望将这些事件发送到的组件也被注册为永久焦点所有者,这有助于消除窗口未聚焦时哪个组件应该接收事件的歧义(KeyboardFocusManager.getGlobalPermanentFocusOwner())

我如何制作一个活动:(非常简单的东西)

public void keyPress(int keycode, char c) {
    KeyEvent press = new KeyEvent(content, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, keycode, c);
    pushEventToQueue(press);
}

public void mousePress(int buttons) {
    MouseEvent press = new MouseEvent(content, MouseEvent.MOUSE_PRESSED,
            System.currentTimeMillis(), buttons, curX, curY, 1, false);
    pushEventToQueue(press);
}

我尝试了什么(以及他们为什么不工作):

  • 通过Component.dispatchEvent(event)调度事件。这不起作用,因为它需要组件可见,因为它通过KeyboardFocusManager路由(奇怪的是)。

  • 出于上述原因,通过KeyboardFocusManager.dispatchEvent(event)调度事件。

  • 调用Component.requestFocus()或.requestFocusInWindow()将允许事件被传递,但是因为它们强制Window容器也被聚焦,所以不能为我工作,这会将窗口带到前景。

  • 通过永久焦点所有者的侦听器进行迭代,并使用我的自定义事件调用事件函数。我不确定为什么这不起作用,但我怀疑它与正常应用功能中不同焦点所有者缺乏传播有关。

这是我当前的pushEventToQueue函数,其中包含的注释失败部分供您娱乐:

    private void pushEventToQueue(AWTEvent evt) {
        //      Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(evt);
//      Component perm = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
//      if (perm == null) {
//          content.dispatchEvent(evt);
//      } else {
//          if (evt instanceof KeyEvent) {
//              for (KeyListener l:perm.getKeyListeners()) {
//                  if (evt.getID() == KeyEvent.KEY_PRESSED)
//                      l.keyPressed((KeyEvent) evt);
//                  else if (evt.getID() == KeyEvent.KEY_RELEASED)
//                      l.keyReleased((KeyEvent) evt);
//                  else if (evt.getID() == KeyEvent.KEY_TYPED)
//                      l.keyTyped((KeyEvent) evt);
//              }
//          } else if (evt instanceof MouseEvent) {
//              for (MouseListener l:perm.getMouseListeners()) {
//                  if (evt.getID() == MouseEvent.MOUSE_PRESSED)
//                      l.mousePressed((MouseEvent) evt);
//                  else if (evt.getID() == MouseEvent.MOUSE_RELEASED)
//                      l.mouseReleased((MouseEvent) evt);
//                  else if (evt.getID() == MouseEvent.MOUSE_CLICKED)
//                      l.mouseClicked((MouseEvent) evt);
//              }
//          } else
//              perm.dispatchEvent(evt);
//      }
        content.dispatchEvent(evt);
        try {
            Thread.sleep(50); //Minimal but necessary
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

我现在唯一能想到的就是扩展KeyboardFocusManager类并添加一些功能,这些功能会将焦点默认为我选择的未聚焦组件,当没有窗口时当前的JVM有焦点(也就是所有的Java窗口都在后台)。理想情况下,这不会干扰现有的程序功能,因为它会表现出非默认行为的唯一情况是所有窗口都没有聚焦。

无法更改swing应用程序的代码库。这意味着我无法实现KeyBindings而不是KeyListeners,也无法覆盖swing组件的isFocused / isShowing方法。我能做的就是反射或JDI提供的任何东西,在这种情况下似乎有点无用。

有没有人有这方面的经验?有人可以提供指导吗?

0 个答案:

没有答案