Starting/Stopping while loop with JButton [duplicate] - java

This question already has answers here:
Calling a method from a JButton is freezing a JFrame?
(2 answers)
Display indeterminate JProgressBar while batch file runs
(1 answer)
Something seems wrong with the layout, JButton showing unexpected behaviour at resize of the window
(4 answers)
Closed 5 years ago.
I am trying to make a program that has a toggle button (regular JButton) that when clicked, runs a while loop that runs until the button is clicked again to stop it.
I have done this, however, when I click the button, the entire JFrame freezes because of it being stuck in the while loop, as the loop will run forever until the button is pressed again. However, it is impossible to click the button again because the JFrame freezes. The button itself also just stays blue because the JFrame freezes before the colour change occurs; right before I click the button.
My code looks something like this:
boolean isRunning=false;
private void buttonClickEvent(ActionEvent evt) {
if(isRunning){
isRunning=false;
System.out.println("Stopped running!");
jButton.setText("Start Running");
} else { // BELOW IS THE CODE THAT CAUSES IT TO LOCK
isRunning=true;
jButton.setText("Stop Routine");
while(isRunning){
// DO STUFF
}
}
}
EDIT: I tried doing the following code (below) and it does print the text and allow the colour change to occur in the button, but the UI still freezes quickly afterward.
boolean isRunning=false;
private void buttonClickEvent(ActionEvent evt) {
if(isRunning){
isRunning=false;
System.out.println("Stopped running!");
jButton.setText("Start Running");
} else { // BELOW IS THE CODE THAT CAUSES IT TO LOCK
isRunning=true;
jButton.setText("Stop Routine");
new Thread(new Runnable() {
public void run() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
while(isInRoutine){
System.out.println("lolk");
}
}
});
}
}).start();
}
}

Related

Reentering Method with New Thread in Java with Swing GUI

I am a beginner with multithreading and GUI development in Java with Swing and Window Builder in Eclipse.
I am trying to get a jlabel that shows the status of the program to display text and quickly fade from red to black when a button is pressed and then to disappear in ten seconds.
I tried to combine suggestions for this from several answers on Stack Overflow using a new thread and a timed task (How to fade color from white to black?) and the code works correctly the first time the button is pressed. However, when the button is pressed again and the method is called again, it only briefly blinks red and the text disappears very quickly.
I believe that it is because when the button is pressed a second time the old thread is still running and both are trying to control the label. I obviously found several question on Stack Overflow on how to kill treads in Java (including How do you kill a thread in Java?), but none of them seemed to help in my situation. I am relatively inexperienced with multithreading and Swing GUIs, so I probably made some really dumb mistakes with my code.
Here it the method that is called by a event listener when a button is pressed (this method is in a separate "Program Main" controller class):
private static void setBriefLblStatus(String content) {
one = new Thread() {
public void run() {
setLblStatus(content);
fading = Color.RED;
TimerTask fadingTask = new TimerTask() {
#Override
public void run() {
if (fading.getRed() > 0) {
fading = new Color(fading.getRed() - 1, 0, 0);
setLblStatusColor(fading);
}
}
};
timer = new Timer();
timer.scheduleAtFixedRate(fadingTask, 7, 7);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
setLblStatus("");
}
};
one.start();
}

Change jLabel visibility immediately when jButton action performed [duplicate]

This question already has answers here:
Set JLabel Visible when JButton is clicked in actionPerformed
(3 answers)
set text in label during an action event [duplicate]
(2 answers)
Closed 5 years ago.
I am using NetBeans IDE and I have some problem when I am trying to change jLabel visibility to true:
private void buttonActionPerformed(java.awt.event.ActionEvent evt)
{
LoaderLabel.setVisible(true);
try { sleep(1000000); } catch { ... }
}
The visibility is changed only after the long sleep...
The problem is that I want to make some very intensive calculations in this method, but at the same time present some gif.
Why the jLabel visibility is changed only at the end of the function and how do I fix it?
Thanks! :)
This is because you should set the component's properties in EDT thread (Event Dispatch Thread).
Try:
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
LoaderLabel.setVisible(true);
}
});
or using Lambda in Java 8
EventQueue.invokeLater(() -> LoaderLabel.setVisible(true));

how to using swingworker to a jprogressbar <update> [duplicate]

This question already has answers here:
Can a progress bar be used in a class outside main?
(3 answers)
Closed 8 years ago.
I have a swingworker that will be representing a jProgressbar. This is the code
private Swingworker timeOfProccess;
class Swingworker extends SwingWorker<Object, Object> {
#Override
protected Object doInBackground() throws Exception {
jProgressBar1.setStringPainted(true);
int progress = 0;
setProgress(0);
while (progress <= 100) {
jProgressBar1.setValue(progress);
Thread.sleep(5);
progress++;
}
mainProccess();
return null;
}
#Override
protected void done() {
jProgressBar1.setValue(100);
JOptionPane.showMessageDialog(null, "Proses Selesai");
jProgressBar1.setValue(0);
jProgressBar1.setStringPainted(false);
}
}
private void btnExecuteActionPerformed(java.awt.event.ActionEvent evt) {
timeOfProccess = new Swingworker();
timeOfProccess.execute();}
I dont know, why the progressbar running is uncontrolled. it is so fast to 100% even the process still working. But void done is success to pop-up the JoptionPane after main process end. where is I am lost in my code. thanks..
Visit How to Use Progress Bars where You will find good examples on progress bar along with detail description.
Don't use Thread.sleep() that sometime hangs the whole swing application instead try with Swing Timer that is most suitable for swing application.
Read more How to Use Swing Timers
sample code:
// delay for 1500 mill-seconds
Timer timer = new javax.swing.Timer(1500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// call for your next task
}
});
timer.setRepeats(true); // you can turn off the repetition
timer.start();
How to get the progressbar showing the number 1 - 100 %.
Use JProgressBar#setStringPainted() method to show the percent done status.

JFrame not Displaying JButton in a loop [duplicate]

This question already has an answer here:
While loop with delay makes JFrame unresponsive
(1 answer)
Closed 9 years ago.
I am making a simple PopUp game where the code below calls a new instance of a class called PopUp. PopUp is a Jframe with a button on it. When the constructor is called inside the loop the button is not displayed. However when the loop is removed the button is displayed just fine. Please help me. Thank you.
public void game() {
PopUp p1;
while(!gameover) {
try {
//If block to set the difficulty of the game
if(diff==0)
TimeUnit.MILLISECONDS.sleep(1000);
else if(diff==1)
TimeUnit.MILLISECONDS.sleep(750);
else if(diff==2)
TimeUnit.MILLISECONDS.sleep(500);
else if(diff==3)
TimeUnit.MILLISECONDS.sleep(250);
else if(diff==4)
TimeUnit.MILLISECONDS.sleep(100);
p1 = new PopUp(); //keep
p1.setLocation(((int)(Math.random()*2000)), ((int)(Math.random()*1000)));
popUpsOpen++;
} catch (InterruptedException ex) {
Logger.getLogger(PopUpGame.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Try to call Game constructor with different Thread.
Thread queryThread = new Thread() {
public void run() {
new game();
}
};
queryThread.start();
and in Game constructor show the popup with UI thread
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
p1 = new PopUp(); //keep
p1.setLocation(((int)(Math.random()*2000)), ((int)(Math.random()*1000)));
popUpsOpen++;
}
});
i think the button is not displaying because the UI thread busy with looping,so the button doesnt get chance to rendered by UI thread
place the these statements after the try-catch block, and also check the value of the variable gameover.
p1 = new PopUp(); //keep
p1.setLocation(((int)(Math.random()*2000)), ((int)(Math.random()*1000)));
popUpsOpen++;

java - How to use invokeLater to synchronize some IO with UI

In my java application I am using swing to implement the UI. There is a button called theButton which is engaged with some IO operation in the following timely steps :
the button originally has the text "Click to connect"
then before the connect operation starts I want the theButton reads
"Connecting in progress..."
then the IO operation gets started
once the IO operation is done theButton now reads "connected ( click to disconnect)".
Issue:
I am using the following code, but first of all the button's text doesn't change to "Connecting in progress..." before the IO starts! as well button doenst actually get disabled before the IO starts! What should I do here?
--
// theButton with text "Click to connect is clicked"
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
theButton.setText("Trying to connect...");
theButton.setEnabled(false);// to avoid clicking several times! Some users cannot wait
theButton.repaint();
// doing some IO operation which takes few seconds
theButton.setText("connected ( click to disconnect)");
theButton.setEnabled(true);
theButton.repaint();
}
});
Your problem is here:
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
theButton.setText("Trying to connect...");
theButton.setEnabled(false);
theButton.repaint();
// doing some IO operation which takes few seconds // **********
theButton.setText("connected ( click to disconnect)");
theButton.setEnabled(true);
theButton.repaint();
}
});
The code marked with the ******* comment is running on the EDT and will tie it up freezing your app and all it's painting.
Use a SwingWorker instead to run the code in a background thread.
Note that there is no need to use invokeLater(...) for code in an ActionListener since this code is already running on the EDT by default.
Also get rid of your repaint() calls since they aren't needed and they don't help.
Add a PropertyChangeListener to your SwingWorker to listen for when it is done, and then you can reset your JButton.
Instead do:
// code not compiled nor tested
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
theButton.setText("Trying to connect...");
theButton.setEnabled(false);
MySwingWorker mySwingWorker = new MySwingWorker();
mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
// listen for when SwingWorker's state is done
// and reset your button.
public void propertyChange(PropertyChangeEvent pcEvt) {
if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
theButton.setText("connected ( click to disconnect)");
theButton.setEnabled(true);
}
}
});
mySwingWorker.execute();
}
});
and
// code not compiled nor tested
public class MySwingWorker extends SwingWorker<Void, Void> {
#Override
public void doInBackground() throws Exception {
// doing some IO operation which takes few seconds
return null;
}
}
And be sure to read: Concurrency in Swing.

Categories