JProgressBar Trouble - Won't Display

Discussion in 'Mac Programming' started by wrldwzrd89, Mar 4, 2008.

  1. macrumors G4

    wrldwzrd89

    Joined:
    Jun 6, 2003
    Location:
    Solon, OH
    #1
    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.
     
  2. macrumors 603

    jeremy.king

    Joined:
    Jul 23, 2002
    Location:
    Fuquay Varina, NC
    #2
    code please.
     
  3. thread starter macrumors G4

    wrldwzrd89

    Joined:
    Jun 6, 2003
    Location:
    Solon, OH
    #3
    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!
    }
    }
    
     
  4. macrumors 603

    jeremy.king

    Joined:
    Jul 23, 2002
    Location:
    Fuquay Varina, NC
    #4
    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);
    
    	}
    }
     
  5. macrumors 65816

    Joined:
    Jul 28, 2004
    #5
    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.
     
  6. thread starter macrumors G4

    wrldwzrd89

    Joined:
    Jun 6, 2003
    Location:
    Solon, OH
    #6
    Thanks, I'll try that.
     
  7. macrumors 603

    jeremy.king

    Joined:
    Jul 23, 2002
    Location:
    Fuquay Varina, NC
    #7
    This was going to be my next question ;)
     
  8. thread starter macrumors G4

    wrldwzrd89

    Joined:
    Jun 6, 2003
    Location:
    Solon, OH
    #8
    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.
     
  9. macrumors 603

    jeremy.king

    Joined:
    Jul 23, 2002
    Location:
    Fuquay Varina, NC
    #9
    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
     
  10. thread starter macrumors G4

    wrldwzrd89

    Joined:
    Jun 6, 2003
    Location:
    Solon, OH
    #10
    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
     

Share This Page