run function on JButton press

混江龙づ霸主 提交于 2021-02-09 12:21:54

问题


I'm attempting to make a program in java that uses a robot to press a specific key every few seconds. 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. 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. 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++;

    }

}

回答1:


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. You could create a thread inside of your actionPerformed method and do your work inside of the new thread. 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. 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).




回答2:


You can do something like this using 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();


来源:https://stackoverflow.com/questions/18583413/run-function-on-jbutton-press

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!