I have a JFrame and following components.
JButton = jButton1 Progress Bar = progressBar and its public static JLabel = status and its public static
When button clicks then different statements execute. I want to update my progressbar after each statement. Here is my code
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
Task pbu = new Task(25, "Step 1....");
pbu.execute();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
pbu = new Task(50, "Step 2....");
pbu.execute();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
pbu = new Task(75, "Step 3....");
pbu.execute();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
pbu = new Task(100, "Done");
pbu.execute();
}
Here is my Task Class extended with SwingWorker
public class Task extends SwingWorker{
private int progress;
private String stat;
public Task(int pr, String st) {
progress = pr;
stat = st;
}
@Override
protected Object doInBackground() throws Exception {
NewJFrame1.progressBar.setValue(progress);
NewJFrame1.status.setValue(stat);
return null;
}
}
Any idea how can I solve this problem?
@Override
protected Object doInBackground() throws Exception {
NewJFrame1.progressBar.setValue(progress);
NewJFrame1.status.setValue(stat);
return null;
}
You don't want to update GUI components off of the Swing thread. SwingWorker
provides hooks for doing stuff back on the Event Dispatch Thread, that's what it's designed for. Call the publish
method from doInBackground
and override process
to detail with incremental updates. Or, if you only need to update the GUI when it's finished, override the done()
method.
A very simple example:
//...in some concrete implementation of SwingWorker<Void, Integer>
protected Void doInBackground() throws Exception {
//do 10% of task
doLongOp();
publish(10);
//do another 20% of task
doAnotherLongOp();
publish(20);
return null;
}
protected void process(List<Integer> pieces) {
for (Integer percent : pieces ) {
progressBar.setValue(progressBar.getValue() + percent);
}
}
@mKorbel makes a good point that for the above to work it needs to extend SwingWorker<Void, Integer>
...Void
being the overall return value type (in this case indicating there's no return value) and Integer
being the type of the incremental updates.
If the worker produces an actual final result (that will be retrieved with get()
) then that type can be used in place of Void
. I had left out these details since I didn't include the class declaration.
In addition to the answer from Mark, you really don't want to sleep in the actionPerformed()
method. This method is (if linked to a GUI component) called by the AWT/Swing event dispatch thread, the same thread that also does painting and everything. As long as your method is not finished, your GUI will be blocked.
Do all your waiting in a SwingWorker or another 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