I am having trouble getting my code to 'pause' until the thread is finished. My program is simply a JProgressBar inside a frame. I am using a loop located inside a thread, which loops every 10 milliseconds and adds +1 to the progress bar. The end result will make the bar look animated as its value increases from 0 to 100.
Now, the problem is getting the code to 'wait' until the progress bar hits value 100. As you can see in the code, I would like to have buttons re-enabled only when the progress bar reaches value 100. As of right now, the buttons seem to get re-enabled simultaneously as the progress bar is increasing.
disableButtons();
// loop and animate the progress bar
for (int i = 0; i <= 100; i++) {
Game.setProgBar_loading(i);
// wait a number of milliseconds
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
}
enableButtons();
You could nest Loading
class in Program
and then access Program
's variables from there, and then pretty much copy this part of the code: // <TODO> re-enable all buttons
into the end of the loop. Something like this:
class Program {
// assuming you have these buttons:
private JButton button1;
private JButton button2;
private JButton button3;
// snip
public Program() {
// assuming there's initialization code for the above buttons somewhere...
// button1 = new ...
// button2 = new ...
// button3 = new ...
// frame initializing
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setBounds(100, 100, 890, 480);
getContentPane().setLayout(null);
setVisible(true);
// create the loading bar
loadingBar = new JProgressBar();
loadingBar.setBounds(10, 11, 864, 23);
getContentPane().add(loadingBar);
// <TODO> disable all buttons
button1.setEnabled(false);
button2.setEnabled(false);
button3.setEnabled(false);
// animate the loading bar
Loading thread = new Loading();
new Thread(thread).start();
// do not re-enable the buttons here yet.
}
// snip
public class Loading implements Runnable {
@Override
public void run() {
// loop and increment loading bar's value
for (int i = 0; i <= 100; i++) {
Program.setProgressBar(i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
}
// re-enable the buttons here instead
button1.setEnabled(true);
button2.setEnabled(true);
button3.setEnabled(true);
}
}
}
EDIT: To generalize your Loading
class and reuse it later you could create an interface that contains methods such as beforeExecute()
and afterExecute()
. Take that interface as an argument to Loading
's constructor and save it as a member so you can later call the interface's methods from within run()
:
public interface LoadingHandler {
public void beforeExecute();
public void afterExecute();
}
public class Loading implements Runnable {
private LoadingHandler handler;
public Loading(LoadingHandler handler) {
this.handler = handler;
}
@Override
public void run() {
// disableButtons();
// use interface's methods instead:
handler.beforeExecute();
// loop and animate the progress bar
for (int i = 0; i <= 100; i++) {
Game.setProgBar_loading(i);
// wait a number of milliseconds
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
}
// enableButtons();
// use interface's method instead:
handler.afterExecute();
}
}
Then, in your GUI's thread you would do something like this:
Loading thread = new Loading(new LoadingHandler() {
@Override
public void beforeExecute() {
disableButtons();
}
@Override
public void afterExecute() {
enableButtons();
}
});
new Thread(thread).start();