简体   繁体   English

在JButton按下运行功能

[英]run function on JButton press

I'm attempting to make a program in java that uses a robot to press a specific key every few seconds. 我正在尝试在java中创建一个程序,它使用机器人每隔几秒钟按一个特定的键。 It has a GUI with a start and stop button and a label which tells which state its in. I've got everything working so far except that when I click "start" it runs the loop for my robot function (which is infinite) it doesn't enable the stop button like I thought it would. 它有一个带有开始和停止按钮的GUI和一个告诉它进入哪个状态的标签。到目前为止我已经完成了所有工作,除了当我点击“开始”它运行我的机器人功能的循环(这是无限的)它不像我想的那样启用停止按钮。 I know its something stupid with where the infinite loop is placed but I'm not sure how to make it work correctly. 我知道无限循环放置的地方有些愚蠢,但我不确定如何让它正常工作。

I don't do a lot of java work, this was just a fun thing I thought to try but got stuck part way through. 我不做很多java工作,这只是一个有趣的事情,我想尝试但是被困住了一段时间。 Any help is appreciated. 任何帮助表示赞赏。

import java.awt.AWTException;
import java.awt.FlowLayout;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Main extends JFrame {

    /**
    * 
    */
    private static final long serialVersionUID = 1L;
    private static boolean running = false;;
    private JButton start_button;
    private JButton stop_button;
    private JLabel tl;
    private static int i = 0;
    Robot robot;

    void start() {

        JFrame frame = new JFrame("Helper");
        tl = new JLabel("Running: " + running);
        start_button = new JButton("Start");
        stop_button = new JButton("Stop");
        stop_button.setEnabled(false);
        frame.add(tl);
        frame.add(start_button);
        frame.add(stop_button);
        frame.setSize(300, 100);
        frame.setVisible(true);
        frame.setLayout(new FlowLayout());
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setLocation(400, 400);

        try {
            robot = new Robot();
        } catch (AWTException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }
        robot.setAutoDelay(200);

        start_button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                start_button.setEnabled(false);
                stop_button.setEnabled(true);
                running = true;
                tl.setText("Running: " + running);
                while (running) {
                    robot_loop(robot);
                }

            }
        });
        stop_button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                start_button.setEnabled(true);
                stop_button.setEnabled(false);
                running = false;
                tl.setText("Running: " + running);

            }
        });

    }

    public static void main(String[] args) {
        new Main().start();

    }

    private static void robot_loop(Robot robot) {

        robot.keyPress(KeyEvent.VK_NUMPAD0);
        robot.keyRelease(KeyEvent.VK_NUMPAD0);

        System.out.println("numpad 0 pressed! - " + i);
        i++;

    }

}

I've adapted my comment into an answer. 我已将我的评论改编成答案。

The actionPerformed method of those event listeners are invoked on Swing's event dispatch thread, and since you're entering into an infinite loop, it'll cause the GUI to freeze. 在Swing的事件调度线程上调用这些事件侦听器的actionPerformed方法,并且由于您进入无限循环,它将导致GUI冻结。 You could create a thread inside of your actionPerformed method and do your work inside of the new thread. 您可以在actionPerformed方法中创建一个线程,并在新线程内部完成工作。 Though the next issue you'd run into is finding a nice way to stop the thread whenever the user presses the stop button. 虽然您遇到的下一个问题是找到一种很好的方法来在用户按下停止按钮时停止该线程。

What's cool is that you've already got all the logic to do this in your code. 很酷的是,你已经在代码中完成了所有逻辑。 So getting it to work is as simple as changing: 让它工作就像改变一样简单:

    start_button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            start_button.setEnabled(false);
            stop_button.setEnabled(true);
            running = true;
            tl.setText("Running: " + running);
            while (running) {
                robot_loop(robot);
            }

        }
    });

To do your work on its own thread: 要在自己的线程上完成工作:

    start_button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            start_button.setEnabled(false);
            stop_button.setEnabled(true);
            running = true;
            tl.setText("Running: " + running);
            Executors.newSingleThreadExecutor().submit(new Runnable() {
                @Override public void run() {
                    while (running) {
                        robot_loop(robot);
                    }
                }
            });
        }
    });

The code above makes use of the executors framework (java.util.concurrent.*) rather than directly creating a thread. 上面的代码使用了执行程序框架(java.util.concurrent。*),而不是直接创建一个线程。 Another alternative as nachokk suggested would be to use a timer java.util.Timer or javax.swing.Timer (either should be fine in this case). nachokk建议的另一种方法是使用计时器java.util.Timerjavax.swing.Timer (在这种情况下应该没问题)。

You can do something like this using SwingTimer 你可以使用SwingTimer做这样的事情

        int delay = 400*1000;// you can inject this property 
        ActionListener taskPerformer = new ActionListener(){
              @Override
              public void actionPerformed(ActionEvent evt2) {
                 robot_loop(robot);
              }

        };

            Timer timer = new Timer(delay, taskPerformer);
            timer.start();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM