Java 将KeyEvents分派到未聚焦的组件

Java 将KeyEvents分派到未聚焦的组件,java,swing,events,awt,keyboardfocusmanager,Java,Swing,Events,Awt,Keyboardfocusmanager,以下是场景: 我有两个java应用程序。第一个是一个使用swing GUI的可视化应用程序,全部封装在JFrame中,JFrame具有非常复杂的行为(非常旧的代码库),我无法更改这些行为。我只是有一个JFrame对象的钩子 第二个应用程序是我正在编写的,它基本上是第一个应用程序的单元测试程序。使用JFrame钩子和JDI,我已经能够完成执行这些测试所需的所有内省,这些测试进行得非常顺利。事实上,我的测试进行得很顺利,我想在后台运行它们。但是,由于我的许多测试都涉及将KeyEvents和Mouse

以下是场景: 我有两个java应用程序。第一个是一个使用swing GUI的可视化应用程序,全部封装在JFrame中,JFrame具有非常复杂的行为(非常旧的代码库),我无法更改这些行为。我只是有一个JFrame对象的钩子

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

在KeyboardFocusManager不停止其进程的情况下,如何“强制”将事件分派到某些swing组件

重要提示:我希望向其发送这些事件的组件也注册为永久焦点所有者,这有助于消除当窗口未聚焦时哪个组件应该接收事件的模糊性(KeyboardFocusManager.getGlobalPermanentFocusOwner())

我如何举办活动:(非常简单的事情)

我尝试过的(以及为什么没有成功):

  • 通过组件分派事件。分派事件(事件)。这不起作用,因为它要求组件在通过KeyboardFocusManager时可见(奇怪的是)

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

  • 调用Component.requestFocus()或.requestFocusInWindow()将允许传递事件,但对我来说不起作用,因为它们也会强制聚焦窗口容器,从而将窗口带到前台

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

以下是我当前的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窗口都在后台),这些功能将默认将焦点放在我选择的未聚焦组件上。理想情况下,这不会干扰现有的程序功能,因为它显示非默认行为的唯一情况是所有窗口都未聚焦

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


有人有这方面的经验吗?有人能提供指导吗?

从代码行
睡眠开始的问题(随机(20,50)),供rest发布SSCCE/MCVE,简短、可运行、可编译,或在此处搜索…为什么使用私有void pushEventToQueue(AWTEvent evt){,清除EDT,您可能会丢失一些未在EDT中执行的事件==由您决定我无法更改swing应用程序的代码库。==您必须接受,这离目标还有很长的路要走,最长的路要走options@mKorbel请随意替换任意长的调用,而不是随机调用。我忘了在代码中包含它ust修复了它。我知道这是所有选项中最困难的解决方案。当您的测试发现错误时会发生什么,因为您无法修改Swing应用程序代码?
    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();
        }
    }