Basic Indeterminate JProgress Bar Usage

18,771

Your current code shows no creation of a background thread, but rather it shows you trying to queue code on the Swing thread from within the Swing thread which doesn't make sense for this problem (although there are occasional times when you may want to do this, but again, not here). The only way for this to succeed is to use a background thread. The standard Oracle JProgressBar tutorial and Concurrency in Swing goes through all of this.

The basic thing is that you must update the JProgressBar from the Swing Thread will doing your long-running process in the background thread, such as that provided by a SwingWorker object. There are too many details for us to review all here, and so all I can do is provide a link, but we'll be happy to help you understand the details once you review the tutorials. Just check the tutorials and come on back with your specific questions if you're still stuck.

Edit 1
You state:

can I just create a new thread object within the buttonClicked() function?

Yes, you can create a SwingWorker object inside of the buttonClicked() method and execute it there.

The thing is I have my API and library of all the functionality that I'm developing the GUI to, and it seems like a longwinded workaround to wrap that function call in a thread.

Sorry, but I have no idea what you're saying here or what issues you think threading will cause. The buttonClicked() method likely must run on the EDT and not in a background thread.

Also note that in most of my more complex Swing GUI's, I often do my file downloading in a different (model) object and create my SwingWorker in a different object still (control) from the GUI object (the view). It may seem more complicated to do it this way, but it's a lot easier to debug, maintain and enhance my program when I do it this way, especially when I heavily use interfaces to allow me to test all program components in isolation.

Edit 2
Some corrections to your solution post. You posted:

public void buttonClicked() {
  class MyWorker extends SwingWorker(String, Object) {
     protected String runInBackground() {
       progressBar.setVisible(true);
       progressBar.setIndeterminate(true);

       // ...

which has problems

  • it's doInBackground(), not runInBackground()
  • but more importantly, you're making Swing calls from within a background thread, something that should never be done (unless the call is thread safe, and even then...).

So change it:

public void buttonClicked() {
  progressBar.setVisible(true);
  progressBar.setIndeterminate(true);
  class MyWorker extends SwingWorker<String, Void> {
     protected String doInBackground() {

       // ...
Share:
18,771

Related videos on Youtube

Bill VB
Author by

Bill VB

Updated on June 09, 2022

Comments

  • Bill VB
    Bill VB almost 2 years

    I simply want to have an indeterminate JProgressBar animate in the bottom left corner of my frame when a long download is being done.

    I've looked through many tutorials, none of which are clear to me. I simply want to have it animate while the file is being downloaded in the background. Each way I've tried this, it doesn't animate the progress bar until after the download is done.

    I need help knowing where to place my download() call.

    class MyFunClass extends JFrame {
      JProgressBar progressBar = new JProgressBar();
    
      public void buttonClicked() {
        progressBar.setVisible(true);
        progressBar.setIndeterminate(true);
    
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            progressBar.setIndeterminate(true);
            progressBar.setVisible(true);
    
            // Do I do my download() in here??
    
        }});
    
        // Do download() here???
        progressBar.setVisible(false);
      }
    }
    

    Thanks in advance!



    Solution

    Edit: For those who have a similar issue to me in the future, this is the basic solution for a basic problem. This isn't my code verbatim, but a general sketch. Inside buttonClicked():

    public void buttonClicked() {
      class MyWorker extends SwingWorker(String, Object) {
         protected String doInBackground() {
           progressBar.setVisible(true);
           progressBar.setIndeterminate(true);
    
           // Do my downloading code
           return "Done."
         }
    
         protected void done() {
            progressBar.setVisible(false)
         }
      }
    
      new MyWorker().execute();
    
    }
    
    • Hovercraft Full Of Eels
      Hovercraft Full Of Eels almost 12 years
      Please see Edit 2 to my answer to crrect some problems.
  • Bill VB
    Bill VB almost 12 years
    can I just create a new thread object within the buttonClicked() function? The thing is I have my API and library of all the functionality that I'm developing the GUI to, and it seems like a longwinded workaround to wrap that function call in a thread.
  • Bill VB
    Bill VB almost 12 years
    Thank you for your time so far. I'm going along with that approach and I'll mark the answer accepted once I get this working. It's a wee frustrating that building a simple GUI for my otherwise well constructed protocol library is turning out to take so much more time and code than I thought it originally would be..
  • Hovercraft Full Of Eels
    Hovercraft Full Of Eels almost 12 years
    @B.VB: frustrating yes, but unavoidable, in any language. You can't step on the thread that is interacting with the user or drawing the GUI if you want your GUI to remain responsive, and so background threading for these situations is a must.