PDA

View Full Version : JProgressBar Trouble - Won't Display




wrldwzrd89
Mar 4, 2008, 09:05 AM
I am having some trouble getting a JProgressBar to display the second time I make the JFrame that contains it visible. The same thing happens if I replace the JProgressBar with a JLabel.

Here's what happens:
I create the JFrame and JProgressBar, setting their initial states, but leave them hidden.
When it's time to show them I make the container JFrame visible, which makes the JProgressBar visible. Everything works fine.
After the task is done I hide the JFrame.
When it's time to do that task again, I make the JFrame visible again... but this time, there's an empty space where the JProgressBar should be.

I've tried the following things to make this work properly:
Recreating the JFrame and JProgressBar every time I want to display it
Force-repainting the JFrame
Packing the JFrame (to see if the JProgressBar was being removed from the JFrame)

None of these worked. I'm utterly baffled. :confused:
By the way, I'm using Eclipse Europa as my IDE, if that makes any difference.



jeremy.king
Mar 4, 2008, 09:38 AM
code please.

wrldwzrd89
Mar 4, 2008, 09:48 AM
code please.

<snip imports, packages>
class Test {
// Fields
JFrame generatorFrame;
JProgressBar generatorProgress;

// Constructors
public Test() {
this.generatorFrame = new JFrame("Generating...");
this.generatorProgress = new JProgressBar();
this.generatorProgress.setIndeterminate(true);
this.generatorFrame.getContentPane().add(this.generatorProgress);
}

// Methods
public doLongTask() {
// Show progress
this.generatorFrame.setVisible(true);
// Really long task code goes here
// Task done, hide progress
this.generatorFrame.setVisible(false);
}
}

public class TestDriver
{
public static void main(String[] args) {
Test t = new Test();
t.doLongTask(); // Works
// Do some other stuff
t.doLongTask(); // Doesn't work!
}
}

jeremy.king
Mar 4, 2008, 10:32 AM
Don't know. I tried this on work machine (PC) and it works fine. Are you manipulating the progress bar at all during your long task?

package test.jpb;

import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JProgressBar;

class Test {
// Fields
JFrame generatorFrame;
JProgressBar progressBar;

// Constructors
public Test() {
generatorFrame = new JFrame("Generating...");
generatorFrame.setPreferredSize(new Dimension(300, 100));
progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
generatorFrame.getContentPane().add(this.progressBar);

generatorFrame.pack();
}

// Methods
public void doLongTask() {
generatorFrame.setVisible(true);
delay();
// Task done, hide progress
this.generatorFrame.setVisible(false);
delay();
}

private void delay() {
// wait for 5 secs
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static void main(String[] args) {
Test t = new Test();

t.doLongTask(); // Works
// Do some other stuff
t.doLongTask(); // Doesn't work!

System.exit(0);

}
}

Amdahl
Mar 4, 2008, 11:48 AM
The PC example works for me on OSX. A common problem in Java is manipulating Swing components outside the Swing thread of execution. If you are making those items visible or hiding, etc, and it is in a thread you created or you aren't doing it in an event handler, that may be the problem. Instead, you have to use something like this:

SwingUtilities.invokeAndWait( new Runnable() {
public void run() { generatorFrame.setVisible(true); }
});


That causes the code in the run() to be executed in the thread for the GUI. You can also do invokeLater(), and it will run it in the other thread when it gets around to it, instead of waiting for it to run immediately.

wrldwzrd89
Mar 4, 2008, 12:19 PM
The PC example works for me on OSX. A common problem in Java is manipulating Swing components outside the Swing thread of execution. If you are making those items visible or hiding, etc, and it is in a thread you created or you aren't doing it in an event handler, that may be the problem. Instead, you have to use something like this:

SwingUtilities.invokeAndWait( new Runnable() {
public void run() { generatorFrame.setVisible(true); }
});
That causes the code in the run() to be executed in the thread for the GUI. You can also do invokeLater(), and it will run it in the other thread when it gets around to it, instead of waiting for it to run immediately.
Thanks, I'll try that.

jeremy.king
Mar 4, 2008, 12:55 PM
A common problem in Java is manipulating Swing components outside the Swing thread of execution.

This was going to be my next question ;)

wrldwzrd89
Mar 4, 2008, 01:52 PM
I think I've figured out what's going on. After some experimenting, I realized that subsequent calls that run the long task run in the event dispatcher thread - and since the dispatcher's busy with the long task it can't process repainting the progress bar. This explains entirely the behavior I am seeing. Is there any way I can force this task to always run in its own thread? If I did that, that should solve the problem.

jeremy.king
Mar 4, 2008, 02:08 PM
I think I've figured out what's going on. After some experimenting, I realized that subsequent calls that run the long task run in the event dispatcher thread - and since the dispatcher's busy with the long task it can't process repainting the progress bar. This explains entirely the behavior I am seeing. Is there any way I can force this task to always run in its own thread? If I did that, that should solve the problem.

You can create your own thread for the processing. Consider using a SwingWorker or something similar. Theres a good example in the Java tutorial (ProgressBarDemo.java) - http://java.sun.com/docs/books/tutorial/uiswing/components/progress.html#bars

wrldwzrd89
Mar 4, 2008, 02:45 PM
You can create your own thread for the processing. Consider using a SwingWorker or something similar. Theres a good example in the Java tutorial (ProgressBarDemo.java) - http://java.sun.com/docs/books/tutorial/uiswing/components/progress.html#bars
That did the trick. I just had to solve a few concurrency issues after that - which I was able to solve. Thank you so much! :D