【问题标题】:How to detect when a button has been pressed in an external Java application?如何检测外部 Java 应用程序中何时按下按钮?
【发布时间】:2013-06-20 07:42:09
【问题描述】:

我需要在没有Automation API 的情况下将自定义拼写检查器集成到现有的Java 应用程序中。

它应该像这样工作:

  1. 在外部应用程序A 中,用户打开一个窗口,他/她在其中输入一些文本。在那个窗口中有一个“拼写检查器”按钮。
  2. 当用户按下“拼写检查”按钮时,我的程序 B 应该从 A 的文本字段中读取文本并将其放入自定义拼写检查中。

如何检测到在外部Java 应用程序中按下了某个按钮?

更新 1:我尝试安装自己的 AWT 事件侦听器来检测其他应用程序中的事件。

    Toolkit.getDefaultToolkit().addAWTEventListener(new MyAWTEventListener(), AWTEvent.MOUSE_MOTION_EVENT_MASK);

    while (true)
    {
        Thread.sleep(1);
    }

但它不起作用。

更新 2:替换系统事件队列也不起作用。

private void queuePushingExperiment() throws InterruptedException,
        InvocationTargetException {
    EventQueue queue = Toolkit.getDefaultToolkit().getSystemEventQueue();

    queue.push(new MyEventQueue());

    EventQueue.invokeAndWait(new Runnable() {

        @Override
        public void run() {
            System.out.println("run");
        }
    });
}

public class MyEventQueue extends EventQueue {

    @Override
    public SecondaryLoop createSecondaryLoop() {
        System.out.println("createSecondaryLoop");
        return super.createSecondaryLoop();
    }

    @Override
    protected void dispatchEvent(AWTEvent event) {
        System.out.println("dispatchEvent");
        super.dispatchEvent(event);
    }

    @Override
    public AWTEvent getNextEvent() throws InterruptedException {
        System.out.println("getNextEvent");
        return super.getNextEvent();
    }

    @Override
    public AWTEvent peekEvent() {
        System.out.println("peekEvent");
        return super.peekEvent();
    }

    @Override
    public AWTEvent peekEvent(int id) {
        System.out.println("peekEvent");
        return super.peekEvent(id);
    }

    @Override
    protected void pop() throws EmptyStackException {
        System.out.println("pop");
        super.pop();
    }

    @Override
    public void postEvent(AWTEvent theEvent) {
        System.out.println("postEvent");
        super.postEvent(theEvent);
    }

    @Override
    public void push(EventQueue newEventQueue) {
        System.out.println("push");
        super.push(newEventQueue);
    }

}

更新 3: java.awt.Window.getOwnerlessWindows()EventQueueMonitor.getTopLevelWindows() 都返回空数组,即使在调用时打开了 JFrame

更新 4: 我注意到我无法写入文件 C:\Program Files\Java\jdk1.7.0_25\jre\lib\accessibility.properties,目前 assistive_technologies=com.sun.java.accessibility.AccessBridge 行已被注释掉。这可能会导致可访问性对象出现上述问题。

【问题讨论】:

  • 你能把A的代码改一下吗?
  • 没有。如果可以的话,任务会很容易的。
  • 确实如此。我认为您所能做的就是收听特定于操作系统的消息。例如,WIN 操作系统上的 Windows 消息。这是一个非常残酷的解决方案,我不确定 java 是否允许这样做。
  • 你不能改变A的代码,但是拼写检查是由它启动的......他们确实必须修改A才能做到这一点,对吧?您不能告诉他们将文本复制到一个文件中,该文件将作为参数传递给拼写检查器吗?
  • 你能在同一个 jvm 实例上运行 bth A 和 B 应用程序吗?

标签: java swing


【解决方案1】:

我怎样才能做到这一点?我认为对于每个 Java 程序都会启动一个单独的 JVM。

实际上java应用A可以从应用B运行。你只需调用A的main()方法。所以实际上你启动 B.main() 运行必要的 B 代码,然后调用 A.main() 来运行 A。在这种情况下,你可以使用 Window 类方法启动窗口(或框架)。

public static Window[] getWindows()

之后,只需查看找到的 Window 的所有子组件,检查它们的类,当你找到 JButton 时,检查按钮的文本或图像以找到必要的实例。然后在那里添加你的监听器。

【讨论】:

  • 如果我编写一个代理并使用 com.sun.tools.attach.VirtualMachine.attach(...) 将其附加到应用程序 A 的 JVM 上,您的方法是否可行?
  • 是的,我正在尝试实现本教程中的示例 - nongreedy.ru/java/2012/10/14/mustangs-attach-api-experiments(俄语)。
  • 我明白了。俄语还行。非常有趣的工具和实验。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-23
  • 2015-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多