我有两个线程。一种是从我的 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/