我已经为我的问题搜索了一个解决方案,但我找不到任何接近的东西。这是我的问题:我刚开始学习Java中的Swing,我有一个应用程序,它会在最短和最长时间之间随机点击。用户输入最小和最大时间,然后单击启动此代码的按钮:
class CalcButtonListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent arg0) {
//get data from text fields and store as integers in milliseconds.
//create a robot and random number between min and max
while(run == true){
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.delay(num.nextInt(max-min+1)+min);
}
}
}
}
我删除了一些代码,因为它与问题无关。 问题是我有另一个按钮将变量run设置为false但是一旦点击第一个按钮,我就无法点击顶部的第二个按钮或退出按钮。
我确定我的错误是一个非常基本的错误,但我看不到它。 感谢您的任何回复,以帮助我更好地理解这一主题。
编辑:将while循环从“while(run = true)”更改为“while(run == true)”。
答案 0 :(得分:4)
while(run == true){
“=”将运行设置为true “==”将run的值与true进行比较
你也可以使用
while(run){
答案 1 :(得分:3)
看看SwingWorker。只需while(run)
答案 2 :(得分:2)
每个事件都将由一个名为Event Dispatch thread(EDT)的线程处理。如果您在其中一个事件中有无限调用,则EDT无法处理事件队列中的下一个事件。
答案 3 :(得分:2)
<强>更新强>
这个答案已经更新了,因为@uckelman指出我,在条件run = true
的情况下,停止按钮永远不会打破while循环,因为在循环中需要将其更改为run = false。然后我发布一个简单的替代解决方案来解决这个逻辑问题,用计时器重复安排一个任务。有关详细信息,请查看this SO问题。
关于按钮的事件:如果你有两个按钮,一个用于启动循环,另一个用于结束循环,只需尝试以下代码:
class CalcButtonListener implements ActionListener{
private boolean run = true;
private java.util.Timer timer = new java.util.Timer();
private JButton start_loop, end_loop;
//here the buttons initialization
@Override
public void actionPerformed(ActionEvent ae){
if(ae.getSource()==start_loop){
java.util.TimerTask task = new java.util.TimerTask() {
@Override
public void run() {
doStuff();
}
};
timer.schedule(task, java.util.Calendar.getInstance().getTime(), 500);//here the '500' means the time, 500 ms,
the task is repeatedly executed.
}
if(ae.getSource()==end_loop){
timer.cancel();//cancel the tasks scheduled
System.out.println("Task cancelled!");
}
}
private void doStuff(){
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.delay(num.nextInt(max-min+1)+min);
}
}
现在,任务doStuff()
计划每500毫秒执行一次。
有关java.util.Timer和java.util.TimerTask的其他信息。
关于您的问题:
问题是我有另一个按钮将变量run设置为false 但是一旦点击第一个按钮,我就无法点击第二个按钮 或者顶部的退出按钮。
Swing的单线程规则说Swing组件只能是 由单个线程访问。此规则适用于获取和设置, 并且单个线程称为事件派发线程。
单线程规则是UI组件的良好匹配,因为它们 无论如何,大多数操作都倾向于以单线程方式使用 由用户发起。此外,建立线程安全 组件既困难又乏味:不做的事情是件好事 如果可以避免的话。但是为了它的所有好处,单线程规则 具有深远的影响。
Swing组件通常不符合单线程规则 除非他们的所有活动都是在事件发送时发送和接收的 线。例如,应该在上发送属性更改事件 应该接收事件派发线程和模型更改事件 事件派遣线程。
对于基于模型的组件,如JTable和JTree,单线程 规则意味着模型本身只能被访问 事件派遣线程。因此,模型的方法必须 快速执行,永远不应阻止,或整个用户界面 将没有反应。
然后,如果使用单个线程开发GUI,则在执行按钮事件时,GUI将冻结,等待相关按钮事件的完整执行。在您的情况下,在无限循环中,您的GUI将始终冻结。
我的建议是为您的GUI使用SwingWorker或扩展Thread类(然后在单独的线程中开发GUI),或实现Runnable接口。另一种方法是使用javax.swing.Timer
包中的Timer。
您可以阅读有关SwingWorker的旧问题:How do I use SwingWorker in Java?
SwingWorker教程:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
制作主题的教程:http://docs.oracle.com/javase/tutorial/essential/concurrency/
关于Timer
:Update JPanel and attributes in a gui, with a user-specified timer?
关于计时器的教程:http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html
答案 4 :(得分:1)
您应该阅读有关Swing计时器的信息:
http://java.sun.com/products/jfc/tsc/articles/timer/
也就是说,让你的程序事件驱动。 Swing应用程序已经有一个循环在它们内部运行,称为事件循环。如果你开始另一个,这没有任何帮助。
答案 5 :(得分:1)
请注意像while(something)
这样的方法,这可能会使程序成为frezee,我建议您实施 事件监听器 以避免此问题... < / p>
答案 6 :(得分:0)
run=true;
while(run == true){
...
答案 7 :(得分:0)
while (run = true)
几乎肯定不是你想要的。这样做的是每次执行循环条件时将true
赋给run
,这可确保循环始终继续。
你可能想说的是while (run == true)
只测试run
是否属实。更好的只是说while (run)
,它做同样的事情。
如果您从其他主题分配给run
,请注意您应该让run
成为您班级的volatile
成员。如果你不在其他地方分配run
,那么你就有一个逻辑错误,因为没有办法摆脱循环。在这种情况下,您需要在循环内添加测试,并在希望循环停止时将run
设置为false。 (或者,您可以拥有while (true)
并在循环中使用break
。)