I am trying to control a while loop in my program to stop and start based on a user input. I have attempted this with a button and the "start" part of it works but then the code goes into an infinite loop which I cant stop without manually terminating it. The following is all my code: Header Class
package test;
import javax.swing.JFrame;
public class headerClass {
public static void main (String[] args){
frameClass frame = new frameClass();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(150,75);
frame.setVisible(true);
}
}
Frame Class
package test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class frameClass extends JFrame {
private JButton click;
public frameClass(){
setLayout(new FlowLayout());
click = new JButton("Stop Loop");
add(click);
thehandler handler = new thehandler();
click.addActionListener(handler);
}
private class thehandler implements ActionListener{
public void actionPerformed(ActionEvent e){
if(e.getSource()==click){
looper loop = new looper();
looper.buttonSet = !looper.buttonSet;
}
}
}
}
Looping class
package test;
public class looper {
public static boolean buttonSet;
public looper(){
while (buttonSet==false){
System.out.println("aaa");
}
}
}
How do I fix this and stop if from going into the infinite loop please?
Generally, in programming languages, to stop a continuous while loop, we use a break statement. However, in Tkinter, in place of the while loop, we use after() to run the defined function in a loop. To break the continuous loop, use a global Boolean variable which can be updated to change the running state of the loop.
Simply press the pushbutton for a few seconds and the Arduino will power on and run code. Then, push and hold the pushbutton until the LED illuminates and then release the button to switch power off.
break is used to exit from a for , while or do… while loop, bypassing the normal loop condition. It is also used to exit from a switch case statement.
The easiest way to jump to begin of loop() is the return; statement. It will leave loop() no matter where you place the command. As loop() is called (invisibly) in a while construct it will start over again.
Swing is a single threaded framework, this means that while the loop is running, the Event Dispatching Thread is been blocked and can't process new events, including repaint requests...
You need to start your Looper class inside it's own thread context. This would also mean that your loop flag would need to be declared volatile
or you should use an AtomicBoolean
so that state can be inspected and modified across thread boundaries
For example...
public class Looper implements Runnable {
private AtomicBoolean keepRunning;
public Looper() {
keepRunning = new AtomicBoolean(true);
}
public void stop() {
keepRunning.set(false);
}
@Override
public void run() {
while (keepRunning.get()) {
System.out.println("aaa");
}
}
}
Then you might be able to use something like...
private class thehandler implements ActionListener {
private Looper looper;
public void actionPerformed(ActionEvent e) {
if (e.getSource() == click) {
if (looper == null) {
looper = new Looper();
Thread t = new Thread(looper);
t.start();
} else {
looper.stop();
looper = null;
}
}
}
}
to run it...
Take a look at Concurrency in Swing and Concurrency in Java for some more details
Also beware, Swing is not thread safe, you should never create or modify the UI from out side the context of the EDT
The problem is you start an infinite loop and try to terminate it in the same thread. That doesn't work because the VM executes one task in a thread after another. It would execute the command to stop the looper
directly after the loop is finished but an infinite loop never finishes. So it cannot be stopped like this.
You need to create a second Thread
for the looper. This way you can stop it from your main thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With