Java线程更新jProgressBar在再次调用线程时不会更新

标签 java multithreading swing jprogressbar

我有两个线程。一种是从我的 BulkProcessor 类运行业务逻辑,该类更新 BulkProcessor.getPercentComplete() 变量:

public void run(){
   new SwingWorker<Void,Void>() {
      protected Void doInBackground() throws Exception {
         BulkProcessor.main(jTextField0.getText(), jTextField1.getText());
         return null;
      };
   }.execute();
}

我的另一个线程是更新 BulkGUI 类中 jProgressBar 的值:

public void update(){
   jProgressBar0.setStringPainted(true);
   jProgressBar0.repaint();
   new SwingWorker<Void,Integer>() {
   protected Void doInBackground() throws Exception {
      do
      {
          percentComplete = BulkProcessor.getPercentComplete();
          publish(percentComplete);
          Thread.sleep(100);
      } while(percentComplete < 100);
      return null;
      } 
      @Override
      protected
      void process(List<Integer> progress)
      {
          jProgressBar0.setValue(progress.get(0));
      }
}.execute();
}

当单击“进程”按钮时,我调用这两个线程:

private void jButton0ActionActionPerformed(ActionEvent event) {
run();
update();
}

第一次运行它完全符合预期。然而,第二次选择 Process 按钮对 jProgressBar 没有影响。更新线程中的局部变量percentComplete 保持为100,并且不会像第一次运行时那样更新。我测试了BulkProcessor 类中的percentComplete 变量,该变量实际上确实按预期更新。因此,由于某种原因,第二次调用线程时,线程不会使用 BulkProcessor.getPercentComplete() 获取更新值。 有人对此有任何见解吗?非常感谢任何帮助。

最佳答案

我猜您的问题可能是因为您第二次按下按钮时percentComplete 是最大的。建议:

  • 每次运行代码时都会重置百分比完成。
  • 避免在后台线程中进行 Swing 调用,包括读取文本字段文本。
  • 最好在 SwingWorker 的构造函数中执行此操作,而不是在其 doInBackground(...) 方法中执行此操作。
  • 您似乎正在进行静态字段和/或方法调用。如果是这样,请不要这样做,因为这最终会给您带来麻烦,而是创建并传递有效的引用。
  • 我猜测为此,您需要创建一个新的 BulkProcessor 对象。
  • 像你正在做的那样调用run(),然后调用update(),让两个线程同时运行对我来说看起来很危险,可能是为了一场比赛健康)状况。

编辑

您应该考虑将 SwingWorker 的进度属性与 PropertyChangeListener 一起使用。例如:

public class FooGUI {

   // .....

   public void myRun() {
      String text1 = someTextField.getText();
      String text2 = otherTextField.getText();
      final BulkProcessor bulkProcessor = new BulkProcessor(text1, text2);
      bulkProcessor.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent pcEvt) {
            if (pcEvt.getPropertyName().equals("progress")) {
               int progress = bulkProcessor.getProgress();
               someProgressBar.setValue(progress);
            }
         }
      });
   }
}

class BulkProcessor extends SwingWorker<Void, Void> {
   private Random random = new Random(); // just for SSCCE sake
   private String text1;
   private String text2;

   public BulkProcessor(String text1, String text2) {
      this.text1 = text1;
      this.text2 = text2;
      // not sure what you do with these texts....
   }

   @Override
   protected Void doInBackground() throws Exception {
      int progress = 0;
      while (progress <= 100) {
         progress = random.nextInt(5); // just as a for instance
                                    // your code will do something else of course
         setProgress(progress);
         Thread.sleep(300);
      }
      return null;
   }

}
<小时/>

例如:

import java.awt.event.*;
import java.beans.*;
import java.util.Random;
import javax.swing.*;

@SuppressWarnings("serial")
public class Foo3 extends JPanel {
   private static final String DEFAULT_SPEED = "15";
   private JTextField speedTextField = new JTextField(DEFAULT_SPEED, 5);
   private JProgressBar someProgressBar = new JProgressBar();
   private RunAction runAction = new RunAction();
   private JButton runButton = new JButton(runAction);

   public Foo3() {
      speedTextField.setAction(runAction);

      add(new JLabel("Speed:"));
      add(speedTextField);
      add(someProgressBar);
      add(runButton);
   }

   public void myRun() {
      String speedText = speedTextField.getText();
      try {
         int speed = Integer.parseInt(speedText);
         final BulkProcessor bulkProcessor = new BulkProcessor(speed);
         bulkProcessor.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent pcEvt) {
               if (pcEvt.getPropertyName().equals("progress")) {
                  int progress = bulkProcessor.getProgress();
                  someProgressBar.setValue(progress);
               }
               if (pcEvt.getPropertyName().equals("state")) {
                  if (bulkProcessor.getState().equals(
                        SwingWorker.StateValue.DONE)) {
                     someProgressBar.setValue(0);
                     setGuiEnabled(true);
                  }
               }
            }
         });
         setGuiEnabled(false);
         bulkProcessor.execute();
      } catch (NumberFormatException e) {
         String text = "Speed of " + speedTextField.getText()
               + " is invalid. Please enter an integer";

         JOptionPane.showMessageDialog(this, text, "Invalid Speed Value",
               JOptionPane.ERROR_MESSAGE);
         speedTextField.setText(DEFAULT_SPEED);
      }
   }

   private class RunAction extends AbstractAction {
      public RunAction() {
         super("Run");
         putValue(MNEMONIC_KEY, KeyEvent.VK_R);
      }

      @Override
      public void actionPerformed(ActionEvent arg0) {
         myRun();
      }

   }

   private void setGuiEnabled(boolean enabled) {
      runButton.setEnabled(enabled);
      speedTextField.setEnabled(enabled);
   }

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

      JFrame frame = new JFrame("Foo3");
      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 BulkProcessor extends SwingWorker<Void, Void> {
   private Random random = new Random(); // just for SSCCE sake
   private int speed;

   public BulkProcessor(int speed) {
      this.speed = speed;
   }

   @Override
   protected Void doInBackground() throws Exception {
      int progress = 0;
      while (progress <= 100) {
         progress += random.nextInt(speed);
         setProgress(progress);
         Thread.sleep(300);
      }
      return null;
   }

}

关于Java线程更新jProgressBar在再次调用线程时不会更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18721816/

相关文章:

c - 多线程-如果满足条件如何停止所有线程?

java - 将标题设置为 JFrame

java - 根据用户的输入调整 JLayeredPane 的大小

java - 如何在Java中从时间(以毫秒为单位)获取ISO格式?

java - 使用指纹进行加密(与密码结合)

c - pthread 程序的臭名昭著的行为

java - 偶尔出现并发修改异常

java - ComboBoxModel - fireIntervalRemoved 的 removeItem 方法抛出异常

java - 在 Java 中执行日期和时间计算

java - 我可以出于测试目的修改字段的值吗?