JProgressBar doesn't update , can't find a clue

流过昼夜 提交于 2019-12-01 22:25:46

I would use a PropertyChangeListener to allow you to make the annealing progress value a "bound" property of the class. Than any observer can follow this property if desired. For example:

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;

@SuppressWarnings("serial")
public class TspGui2 extends JPanel {
   private static final String ANNEALING_PROGRESS = "Annealing Progress";
   private JProgressBar progBar = new JProgressBar(0, 100);
   private JLabel valueLabel = new JLabel();
   private JButton beginAnnealingBtn = new JButton("Begin Annealing");
   private MyAnnealing myAnnealing = new MyAnnealing(this);

   public TspGui2() {
      beginAnnealingBtn.addActionListener(new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent e) {
            beginAnnealing();
         }
      });
      myAnnealing.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent evt) {
            if (evt.getPropertyName().equals(MyAnnealing.ANNEALING)) {
               // be sure this is done on the EDT
               SwingUtilities.invokeLater(new Runnable() {
                  public void run() {
                     int annealedValue = myAnnealing.getAnnealedValue();
                     setValue(annealedValue);
                     if (annealedValue >= MyAnnealing.MAX_ANNEALED_VALUE) {
                        beginAnnealingBtn.setEnabled(true);
                     }
                  }
               });
            }
         }
      });
      progBar.setString(ANNEALING_PROGRESS);
      progBar.setStringPainted(true);

      JPanel northPanel = new JPanel(new GridLayout(1, 0));
      northPanel.add(beginAnnealingBtn);
      northPanel.add(valueLabel);

      setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
      add(northPanel);
      add(progBar);
   }

   public void setValue(int value) {
      valueLabel.setText("Value:" + value);
      progBar.setValue(value);
   }

   public void beginAnnealing() {
      beginAnnealingBtn.setEnabled(false);
      setValue(0);
      myAnnealing.reset();
      new Thread(new Runnable() {
         public void run() {
            myAnnealing.beginAnnealing();
         }
      }).start();
   }

   private static void createAndShowGui() {
      TspGui2 mainPanel = new TspGui2();

      JFrame frame = new JFrame("TspGui2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

class MyAnnealing {
   public static final String ANNEALING = "Annealing";
   public  static final int MAX_ANNEALED_VALUE = 100;
   private SwingPropertyChangeSupport propChangeSupport = 
         new SwingPropertyChangeSupport(this);
   private TspGui2 gui;
   private int annealedValue;

   public MyAnnealing(TspGui2 gui) {
      this.gui = gui;
   }

   public void addPropertyChangeListener(
         PropertyChangeListener listener) {
      propChangeSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(
         PropertyChangeListener listener) {
      propChangeSupport.removePropertyChangeListener(listener);
   }

   public void reset() {
      setAnnealedValue(0);
   }

   // simulate some long process...
   public void beginAnnealing() {
      long sleepDelay = 100;
      while (annealedValue < MAX_ANNEALED_VALUE) {
         setAnnealedValue(annealedValue + 1);
         try {
            Thread.sleep(sleepDelay);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

   public int getAnnealedValue() {
      return annealedValue;
   }

   private void setAnnealedValue(int value) {
      final int oldValue = this.annealedValue;
      this.annealedValue = value;
      propChangeSupport.firePropertyChange(ANNEALING, oldValue, annealedValue);
   }   
}

If you can't use SwingWorker then use SwingUtilities.invokeLater, e.g.:

if (progress != Path.operationProgress) {
    final int progressCopy = progress; // Probably not final so copy is needed
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        void run() {
            operationsProgressBar.setValue(progressCopy);
        }
    });
}

Note: When doing this, everything used in run has to be final or there have to be other measures to access the variables. This code is symbolic in that regard.

You need to do operations on Swing components outside the event dispatching thread, there is no way around this.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!