使用按钮退出无限循环-Java
我到处寻找解决我问题的办法,但我找不到任何接近的办法。这是我的问题:我刚刚开始学习Java中的Swing,我有一个应用程序,它将在最小和最大时间之间随机单击。用户输入最小和最大时间,然后单击启动此代码的按钮:使用按钮退出无限循环-Java,java,swing,Java,Swing,我到处寻找解决我问题的办法,但我找不到任何接近的办法。这是我的问题:我刚刚开始学习Java中的Swing,我有一个应用程序,它将在最小和最大时间之间随机单击。用户输入最小和最大时间,然后单击启动此代码的按钮: class CalcButtonListener implements ActionListener{ @Override public void actionPerformed(ActionEvent arg0) { //get data fro
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);
}
}
}
}
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);
}
}
我删除了一些代码,因为它与问题无关。
问题是我有另一个按钮将变量run设置为false,但是一旦单击了第一个按钮,我就无法单击第二个按钮或顶部的exit按钮
我确信我的错误是非常基本的,但我看不出来。
谢谢你的回复,帮助我更好地理解这个主题
编辑:将while循环从“while(run=true)”更改为“while(run=true)”
“=”将运行设置为true
“==”将run的值与true进行比较
你也可以用
while(run){
看一看。只要边跑边做
每个事件都将由一个称为事件调度线程(EDT)的线程处理。如果在其中一个事件中有无限调用,EDT将无法处理事件队列中的下一个事件。
而(run=true)
几乎肯定不是您想要的。这样做是在每次执行循环条件时将true
赋值给run
,从而确保循环始终继续
您可能想说的是while(run==true)
,它只测试run
是否为true。更好的方法是在(运行)时说,
,这样做同样的事情
如果您从不同的线程分配给
run
,请注意,您应该使run
成为类的volatile
成员。如果您没有分配到其他地方的run
,那么您就有一个逻辑错误,因为无法打破循环。在这种情况下,需要在循环中添加一个测试,并在希望循环停止时将run
设置为false。(或者,您可以使用while(true)
,只需在循环中使用break
。您应该阅读有关摆动计时器的内容:
也就是说,使程序由事件驱动。Swing应用程序中已经有一个循环一直在运行,称为事件循环。如果您启动另一个,则没有任何帮助。更新
这个答案被更新了,因为@uckelman指出,在条件run=true
下,停止按钮永远不会中断while循环,因为需要在循环中更改为run=false。然后我发布了一个简单的替代方案来解决这个逻辑问题,用定时器重复安排一个任务。有关详细信息,请勾选问题
关于按钮的事件:如果有两个按钮,一个用于启动循环,另一个用于结束循环,请尝试以下代码:
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);
}
}
}
}
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毫秒执行一次
关于和的其他信息
关于你的问题:
问题是我有另一个按钮将变量run设置为false
但是一旦第一个按钮被点击,我就不能再点击第二个按钮了
或者顶部的退出按钮
与前一页一样,在第页中,它写了以下内容:
Swing的单线程规则说Swing组件只能是
由单个线程访问。此规则适用于get和set,
单个线程称为事件分派线程
单线程规则非常适合UI组件,因为它们
不管怎样,倾向于以单线程的方式使用大多数操作
正在由用户启动。此外,构建线程安全
组件既困难又乏味:不去做是件好事
如果可以避免的话。但尽管有这么多好处,单线程规则
具有深远的影响
回转组件通常不符合单螺纹规则
除非他们的所有事件都在事件分派中发送和接收
线例如,属性更改事件应在
事件调度线程和模型更改事件应在
事件调度线程
对于基于模型的组件,如JTable和JTree,单线程
规则意味着模型本身只能由
事件调度线程。因此,模型的方法必须
快速执行,不应阻塞整个用户界面
将是无反应的
然后,如果使用单个线程开发GUI,当执行按钮事件时,GUI将冻结,等待相关按钮事件的完全执行。在您的情况下,在无限循环中,您的GUI将始终冻结
我的建议是,对于GUI,使用或扩展类(然后在单独的线程中开发GUI),或实现接口。另一种选择是使用javax.swing.Timer
包中的
你可以阅读关于SwingWorker的这个老问题:
SwingWorker的教程:
制作线程的教程:
关于计时器的问题:
关于计时器的教程:小心像
这样的方法,因为(某物)
,这可能会使程序变得不稳定,我建议您实现事件侦听器以避免出现此问题…因为注释表明机器人将进行单击,也许在EDT之外做这件事不是个好主意。@mKorbel谢谢。我知道在一个单独的actionPerformed方法中使用getSource()的建议,它不是最好的(最好通过内部类来实现),但这是我想到的第一件事。:-)这不能工作,因为run
在while(run)
循环中从未设置为false
。@uckelman为什么不能工作?-->如果(ae.getSource()==end\u循环)run=false;