java - 这就是 Java 中使用自动点击器和 GUI 进行多线程处理的方式吗?

标签 java multithreading swing user-interface

我希望使用 Robot 类在 Java 中创建一个带有 JFrame GUI 的自动点击器。我想知道这是否是在不同线程中创建 GUI 的最佳方法,以便即使在自动点击器/机器人执行操作时它也能保持响应?

我在 Oracle 文档中读到 Swing 对象有自己的事件调度程序线程,所以也许这根本没有必要?如果是这样,那是什么?提前致谢!

package Engine;
import javax.swing.*;
import GUI.UI;

public class Engine {

    private Thread UIthread, clickerThread;
    public UI ui;
    public AutoClicker autoClicker;

    public Engine(int width, int height) {

        ui = new UI(width, height);
        ui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ui.setVisible(true);

        UIthread = new Thread(ui);
        UIthread.start();

        //autoclicker is where the Robot class 
        autoClicker = new AutoClicker();
        clickerThread = new Thread(autoClicker);
        clickerThread.start();
    }



}

这里分别是 UI(及其事件处理程序)和 AutoClicker 类,以防有帮助:

package GUI;

import javax.swing.*;

public class UI extends JFrame implements Runnable{

    public int width, height;
    JButton start, stop;


    public UI(int width, int height) {
        this.width = width;
        this.height = height;
        this.setLayout(null);
        this.setSize(width, height);
    }

    public void init() {
        start = new JButton();
        start.setText("start");
        start.setBounds(100, 100, 100, 30);
        add(start);

        stop = new JButton();
        stop.setText("stop");
        stop.setBounds(100, 140, 100, 30);
        add(stop);

        EventHandler eHandler = new EventHandler(this);
        start.addActionListener(eHandler);
        stop.addActionListener(eHandler);
    }

    @Override
    public void run() {
        init();

    }
}

EventHandler类

    package GUI;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;

    public class EventHandler implements ActionListener{

        private UI ui;

        public EventHandler(UI ui) {
            this.ui = ui;
        }

        public void actionPerformed(ActionEvent actionEvent) {
            if(actionEvent.getSource().equals(ui.start)) {
                //start autoclicking
                System.out.println("start");
            }else if(actionEvent.getSource().equals(ui.stop)) {
                //stop autoclicking 
                System.out.println("stop");
            }

        }

    }

自动点击器类:

package Engine;

import java.awt.AWTException;
import java.awt.Robot;

public class AutoClicker implements Runnable{

    private Robot robot;

    public void run() {

        try {
            robot = new Robot();
            //do mouse clicks and stuff 

        } catch (AWTException e) {
            e.printStackTrace();
        }


    }

}

最佳答案

您正在谈论的事件调度线程确实是您应该与 javax.swing 一起使用来创建响应式 GUI 的线程。当您要显示窗口时,您应该通过 javax.swing.SwingUtilites 类安排 EDT 作业。例如:

import javax.swing.*;

public class HelloWorldSwing {
    private static void createAndShowGUI() {
        // Create and set up the window.
        JFrame frame = new JFrame("HelloWorldSwing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Add the ubiquitous "Hello World" label.
        JLabel label = new JLabel("Hello World");
        frame.getContentPane().add(label);

        // Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        // Schedule a job for the event-dispatching thread:
        // creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

(代码直接取自 HelloWorldSwing.java )

这里的重要部分是在 main 方法中:它确保其他代码可以自由地使用主线程,并且当您下载一个大文件时,GUI 不会变得无响应文件(话又说回来,它也应该在它自己的线程中,具体取决于情况)。

现在,如果我们将您提供的代码放入 Main 类中:

import Engine.*;

public class Main {
    public static void main(String[] args){
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Engine(640, 400);
            }
        });
    }
}

有了这一切,GUI 现在在单独的线程中运行,但在 Engine 类中创建了两个新线程,在某种程度上导致 EDT 有两个子线程。您应该消除 UI 线程;它真正所做的只是在一个单独的线程中向原始窗口添加额外的组件,当你想到它时,这有点矫枉过正。

现在,关于自动点击器。您应该实现这一点,以便当按下“开始”按钮时,会生成一个带有 Runnable 的新线程,只要某个 boolean 值为 true,该线程就会循环,按您想要的速度单击。当按下“停止”按钮时(我的猜测是机器人仍然处于 Activity 状态......),将该 boolean 值设置为 false。这一切都应该在 EventHandler.actionPerformed 方法内。

关于java - 这就是 Java 中使用自动点击器和 GUI 进行多线程处理的方式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45761631/

相关文章:

java - 如何在调度更多事件之前等待 JOptionPane 关闭

java - 从与用户输入匹配的数组列表元素中选择

java - IBM Message Broker Toolkit 安装问题

java - runOnUiThread 方法和 Handler 有什么区别?哪一个最好用?

java - 正则表达式从路径中删除所有目录名(保留文件名)

Java GUI getComponent()、panel.remove()

python - TensorFlow默认使用多少个内核(不使用Coordinator)?

Python:使用多处理进行并行图像读取和预处理

c# - 事件不断引发,减慢代码速度。如何用线程处理它?

java - 有人可以帮助我了解 ImageIcon 在 java 中的工作原理吗?