Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem making a JProgressBar update values in Loop (Threaded)

Am trying to get my program to update the progress bar values constantly within a method while performing some operations. However this does not happen until the end, and the UI freezes.

After looking around to similar questions with my problems, I tried to implement the accepted solutions (Using threads) however I cannot get it to work correctly. Is just like if they where not there.

My program contains several classes, the Main being the one automatically created by netbeans on the JFrame Design mode, so there are certain things such as the static void main and the public Main that am not really sure of some of its contents. Under i will put the snippets of those methods, together with my thread implementation.

public class Main extends javax.swing.JFrame implements ActionListener, Runnable{
                                          // I added implements ActLis, Runn.....

...

static Main _this;      // I included this variable

...

public static void main(String args[]) {
        Main m = new Main();                               // Added by me
        new Thread(m).start();                             // Added by me
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Main().setVisible(true);
            }
        });
 }

...

public Main() {
        initComponents();
        _this = this;        // Added by me
}


...

// I also included these 2 methods in the class

public void actionPerformed(ActionEvent e) {                                    
    synchronized(this){                                                         
        notifyAll();                                                            
    }                                                                           
}                                                                               

public void run() {                                                             
    try{synchronized(this){wait();}}
    catch (InterruptedException e){}
    progressBar.setValue(50);                                                   
}

...

private void buttonPressed(java.awt.event.MouseEvent evt) {
   for(int i=0; i<=100; i++) {
      for(int j=0; j<=5; j++) {
         // does some work
      }
   run();
   }
}

All the things that I commented as I added... are things that I putted according to tutorials and answers I have seen online, but nothing seems to work and it feels like I have tried close to a million different combinations...

Thanks in advance for helping out.

like image 419
Fabian Avatar asked Feb 28 '11 23:02

Fabian


2 Answers

Here's some basis for you to look at, if you can study it and understand why every piece of code is there then I think it will help. Feel free to ask questions in a comment (although I'm going to bed right now!)

Example:

public class ProgressBarDemo extends JFrame {
    private final JProgressBar progressBar = new JProgressBar(0, 100);
    private int progressCounter = 0;

    public ProgressBarDemo() {
        setContentPane(progressBar);
        setPreferredSize(new Dimension(100, 100));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack();
        new Thread(new Runnable() {
            public void run() {
                while (progressCounter <= 100) {
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            progressBar.setValue(progressCounter++);
                        }
                    });
                    try { Thread.sleep(500); } catch (InterruptedException e) {}
                }
            }
        }).start();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new ProgressBarDemo().setVisible(true);
            }
        });
    }
}

Two different ways to approach the problem, using SwingWorker instead:

SwingWorker Example 1:

    ....
    public ProgressBarDemo() {
        setContentPane(progressBar);
        setPreferredSize(new Dimension(100, 100));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack();

        SwingWorker<Integer, Void> worker = new SwingWorker<Integer,Void>() {
            public Integer doInBackground() {
                while (progressCounter <= 100) {
                    setProgress(progressCounter++);
                    try { Thread.sleep(500); } catch (InterruptedException e) {}
                }
                return 0;
            }
        };
        worker.addPropertyChangeListener(new PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent event) {
                if ("progress".equals(event.getPropertyName())) {
                    progressBar.setValue((Integer)event.getNewValue());
                }
            }
        });
        worker.execute();
    }
    ....

SwingWorker Example 2 (not so nice, but interesting nonetheless):

    ....
    public ProgressBarDemo() {
        setContentPane(progressBar);
        setPreferredSize(new Dimension(100, 100));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack();

        new SwingWorker<Integer,Integer>() {
            public Integer doInBackground() { 
                while (progressCounter <= 100) {
                    publish(progressCounter++);
                    try { Thread.sleep(500); } catch (InterruptedException e) {}                    
                }
                return 0;
            }
            public void process(List<Integer> progresses) {
                Integer maxProgress = null;
                for (int progress : progresses) {
                    if (maxProgress == null || progress > maxProgress) {
                        maxProgress = progress;
                    }
                }
                progressBar.setValue(maxProgress);
            }
        }.execute();
    }
    ....
like image 125
Mike Tunnicliffe Avatar answered Nov 15 '22 02:11

Mike Tunnicliffe


There are a few things wrong with your code :(

  • you're creating Main twice, and you end up waiting on one instance and notifying the other.
  • you're manually calling run() as well as schedule a thread to do that too...

forget tutorials, write the code from scratch and only add things to it you understand.

like image 44
iluxa Avatar answered Nov 15 '22 03:11

iluxa