0

I have a problem while creating a JProgressBar which is set to indeterminate. The following code is my implementation of the JProgressBar and is called/constructed from another class:

public class Progress implements Runnable
{
  private JFrame frameProgress;
  private JProgressBar progressBar;

  public Progress(String title, String message)
  {
    try
    {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
    catch (Exception e)
    {
      GlobalVariables.LOGGING_logger.error("Error instatiating progress bar.",
          e);
    }

    UIManager.put("ProgressBar.selectionForeground", Color.black);
    UIManager.put("ProgressBar.selectionBackground", Color.black);

    this.frameProgress = new JFrame(title);
    this.frameProgress.setIconImage(GlobalVariables.GUI_icon.getImage());
    this.frameProgress.setSize(300, 60);
    this.frameProgress.setLocation(16, 16);
    this.progressBar = new JProgressBar();
    this.progressBar.setStringPainted(true);
    this.progressBar.setString(message);
    this.progressBar.setIndeterminate(true);
    this.frameProgress.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.frameProgress.add(this.progressBar);
    this.frameProgress.setResizable(false);
    this.frameProgress.setVisible(true);
  }

  public void start()
  {
    new Thread(this).start();
  }

  public void close()
  {
    this.frameProgress.dispose();
    this.frameProgress = null;
    this.progressBar = null;
  }

  @Override
  public void run()
  {
    SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
        // do nothing, because progress bar is indeterminate
      }
    });
  }
}

The caller of this JProgressBar is the following code snippet:

    Progress p = new Progress("bla", "blub");
    p.start();
    boolean successfull = xmlWriter.writeCommonSettingsFromGUI(this);
    p.close();

And now i want, while the xmlWriter.writeCommonSettingsFromGUI(this); is doing something, that the JProgressBar is shown to the user and is working while the algorithm is running.

How can I achieve this? I don't know so much about threading and searched in many other forums, but I don't found any answer for my question.

Please help me and thank you in advance ;)

EDIT: The Progress JFrame opens up with no content for that time, the algorithm is running.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
marc3l
  • 2,525
  • 7
  • 34
  • 62
  • Can you describe what doesn't work about your current code? – Duncan Jones Apr 11 '13 at 08:07
  • The progress bar doesn't show up and i get an exception:Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at de.Progress$1.run(Progress.java:63) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:727) at java.awt.EventQueue.access$200(EventQueue.java:103))... – marc3l Apr 11 '13 at 08:08
  • Okay...there is no more error....but: If I start the thread, it opens up the Progress JFrame, but no content (no JProgressBar) in it... – marc3l Apr 11 '13 at 08:15
  • Don't add important details as comments. [Edit your question](http://stackoverflow.com/posts/15943621/edit) and add the information. Please include a *full* stacktrace. – Duncan Jones Apr 11 '13 at 08:21
  • No error anymore...was in an older version of this code... – marc3l Apr 11 '13 at 08:23

1 Answers1

3

You are probably facing concurrency issues with Swing. Assuming that the following code runs on the EDT (Event Dispatching Thread):

Progress p = new Progress("bla", "blub");

eventually, this will open a JFrame with a progress bar in it.

  • I would consider using a JDialog instead of a JFrame
  • I would not force the size of the JFrame, but rather call pack()

Then, still running on the EDT (and thus blocking all UI-events such as repaint, mouse clicks, etc...), you call p.start() which starts a new Thread() which will invoke run() which itself calls

SwingUtilities.invokeLater(new Runnable()
{
  public void run()
  {
    // do nothing, because progress bar is indeterminate
  }
});

This basically won't do anything except push an additional event on the EventQueue and it will run after all currently pending events. This event will run... "nothing" since your Runnable is just empty. The new Thread dies almost immediately. So all this code is useless.

Still pursuing on the EDT, you call boolean successfull = xmlWriter.writeCommonSettingsFromGUI(this); (btw, "successful" ends with only one 'l'). This will continue on blocking the EDT, preventing repaints from occurring and preventing the JProgressBar from painting itself. Eventually you will dispose the JFrame but since all this code is running on the EDT, the user will not see much of the progress bar and the UI will look frozen.

Consider reading the Swing tag wiki (especially the very last part with 3 important links).

Using a SwingWorker should help you out in this.

Community
  • 1
  • 1
Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117