Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

wrldwzrd89

macrumors G5
Original poster
Jun 6, 2003
12,110
77
Solon, OH
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.
 

wrldwzrd89

macrumors G5
Original poster
Jun 6, 2003
12,110
77
Solon, OH
code please.
Code:
<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

macrumors 603
Jul 23, 2002
5,479
1
Holly Springs, NC
hmm

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?

Code:
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

macrumors 65816
Jul 28, 2004
1,438
1
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:
Code:
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

macrumors G5
Original poster
Jun 6, 2003
12,110
77
Solon, OH
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:
Code:
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.
 

wrldwzrd89

macrumors G5
Original poster
Jun 6, 2003
12,110
77
Solon, OH
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

macrumors 603
Jul 23, 2002
5,479
1
Holly Springs, NC
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
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.