我正在尝试用java编写一个程序,该程序使用机器人每隔几秒钟按下一个特定的键。它有一个GUI,带有启动和停止按钮,还有一个标签,告诉它处于哪个状态。到目前为止,我已经一切正常,只是当我点击"启动"时,它会为我的机器人功能运行循环(这是无限的),它不会像我想象的那样启用停止按钮。我知道无限循环的位置很愚蠢,但我不知道如何使其正确工作。
我不做很多java工作,这只是一件有趣的事情,我本想尝试一下,但中途被卡住了。感谢您的帮助。
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++;
}
}
我已经将我的评论修改为一个答案。
这些事件监听器的actionPerformed方法在Swing的事件调度线程上调用,由于您进入了一个无限循环,它将导致GUI冻结。您可以在actionPerformed方法中创建一个线程,并在新线程中完成工作。尽管你会遇到的下一个问题是找到一种在用户按下停止按钮时停止线程的好方法。
酷的是,您已经在代码中拥有了执行此操作的所有逻辑。因此,让它发挥作用就像改变一样简单
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);
}
}
});
在自己的线程上完成工作:
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);
}
}
});
}
});
上面的代码使用了executors框架(java.util.concurrent.*),而不是直接创建线程。纳乔克建议的另一种替代方案是使用计时器java.util.Timer
或javax.swing.Timer
(在这种情况下,两者都可以)。
您可以使用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();