使用按钮退出无限循环-Java

使用按钮退出无限循环-Java,java,swing,Java,Swing,我到处寻找解决我问题的办法,但我找不到任何接近的办法。这是我的问题:我刚刚开始学习Java中的Swing,我有一个应用程序,它将在最小和最大时间之间随机单击。用户输入最小和最大时间,然后单击启动此代码的按钮: class CalcButtonListener implements ActionListener{ @Override public void actionPerformed(ActionEvent arg0) { //get data fro

我到处寻找解决我问题的办法,但我找不到任何接近的办法。这是我的问题:我刚刚开始学习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);

            }
        }
    }
}
    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;