您是
doInBackground()直接从代码中调用,类似于
run()在可运行对象中直接调用。这意味着您的代码实际上并没有在后台线程上运行,因此您很可能会用长时间运行的代码破坏事件线程,从而导致Swing
GUI和进度条无法更新。
解决方案:不要这样做。
execute()当您希望它运行时,请呼叫它的工人。
如果您需要进一步的帮助,则首先需要帮助我们。您了解您已经发布了大量的代码,其中大多数代码与您的问题完全无关,而且肯定比您要求志愿者通过的代码还要多。
编辑
您似乎也正在直接从EDT调用代码,这些代码应留在此处的工作线程中:
signalSimulator.execute(); // ************* all these signalSimulator calls below *********** if (rdbtnSineWave.isSelected()) {data = signalSimulator.generateSineWave(numOfdataPoints, noiseAmp, offset);data = signalSimulator.addAnomalies(data, numOfLocalSpikes, numOfExpSpikes); } else { // Linear signal is selecteddata = signalSimulator.generateLinearSignal(numOfdataPoints, noiseAmp, slope, offset);data = signalSimulator.addAnomalies(data, numOfLocalSpikes, numOfExpSpikes); } signalSimulator.writeLogFile(path, ".txt", data);您似乎还只创建了 一个 不合适的工作程序对象,因为您不能重复使用SwingWorker对象。
我建议您仅在需要时创建SwingWorker对象,然后将需要哪种信号的信息传递到其构造函数中。这样,可以从SwingWorker所属的doInBackground方法中调用上述方法。
例如,
signalSimulator = SignalSimulator(rdbtnSineWave.isSelected())signalSimulator.addPropertyChangeListener(...);signalSimulator.execute();
请注意,您在已发布的代码中还存在其他一些不相关的重大问题,但是必须在其他时间解决,但它们包括使用null布局和setBounds,这几乎总是一个非常糟糕的主意。
编辑
再次澄清一下,您的主要问题是您正在Swing事件线程上调用长时间运行的代码。仅仅因为方法位于您的Worker类中并不意味着调用它会自动使它在后台线程上运行。保证这一点的唯一方法是在您的
doInBackground()方法中调用代码。同样,您想要做的是在
需要时 创建新的辅助对象,例如,在某个ActionListener内部,并在创建该辅助对象 时
将所有需要运行的信息传递给该辅助对象。然后添加您的PropertyChangeListener,然后添加您
.execute()的工作程序。这样做,我敢打赌您的代码会更好。
编辑
例如
import java.awt.event.*;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import java.util.Random;import java.util.concurrent.ExecutionException;import javax.swing.*;public class ProgressExampleGui { private JPanel mainPanel = new JPanel(); private JProgressBar progressBar = new JProgressBar(); private JButton pressMeBtn = new JButton(new MyAction("Press Me", KeyEvent.VK_P, this)); public ProgressExampleGui() { progressBar.setStringPainted(true); progressBar.setString(""); mainPanel.add(pressMeBtn); mainPanel.add(progressBar); } public void setProgress(int progress) { progressBar.setValue(progress); progressBar.setString(progress + "%"); } public JComponent getMainComponent() { return mainPanel; } public void setEnabled(boolean enabled) { pressMeBtn.setEnabled(enabled); } private static void createAndShowGui() { ProgressExampleGui progExampleGui = new ProgressExampleGui(); Jframe frame = new Jframe("Progress Example"); frame.setDefaultCloseOperation(Jframe.DISPOSE_ON_CLOSE); frame.getContentPane().add(progExampleGui.getMainComponent()); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); }}@SuppressWarnings("serial")class MyAction extends AbstractAction { private ProgressExampleGui gui; public MyAction(String name, int mnemonic, ProgressExampleGui gui) { super(name); putValue(MNEMONIC_KEY, mnemonic); this.gui = gui; } @Override public void actionPerformed(ActionEvent e) { AbstractButton source = (AbstractButton) e.getSource(); gui.setProgress(0); source.setEnabled(false); MyWorker myWorker = new MyWorker(); myWorker.addPropertyChangeListener(new WorkerPropChngListener(gui)); myWorker.execute(); }}class WorkerPropChngListener implements PropertyChangeListener { private ProgressExampleGui gui; public WorkerPropChngListener(ProgressExampleGui gui) { this.gui = gui; } @Override public void propertyChange(PropertyChangeEvent pcEvt) { MyWorker myWorker = (MyWorker) pcEvt.getSource(); if ("progress".equals(pcEvt.getPropertyName())) { int progress = ((Integer)pcEvt.getNewValue()).intValue(); gui.setProgress(progress); } if (SwingWorker.Statevalue.DONE.equals(pcEvt.getNewValue())) { try { myWorker.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } gui.setEnabled(true); } }}class MyWorker extends SwingWorker<Void, Void> { private static final int MAX_INCR = 8; private static final long SLEEP_TIME = 200; private static final int MAX_VALUE = 100; private int value = 0; private Random random = new Random(); @Override protected Void doInBackground() throws Exception { while (value < MAX_VALUE) { value += random.nextInt(MAX_INCR); value = Math.min(value, MAX_VALUE); Thread.sleep(SLEEP_TIME); setProgress(value); } return null; }}编辑
关于新代码,您有两个 主要 问题:
查看数据输出的结果:
Value in setProgress: 0.0Value in setProgress: 0.001Value in setProgress: 0.002Value in setProgress: 0.003Value in setProgress: 0.004Value in setProgress: 0.005Value in setProgress: 0.006Value in setProgress: 0.007Value in setProgress: 0.008Value in setProgress: 0.009Value in setProgress: 0.01Value in setProgress: 0.011Value in setProgress: 0.012Value in setProgress: 0.013Value in setProgress: 0.014Value in setProgress: 0.015Value in setProgress: 0.016Value in setProgress: 0.017Value in setProgress: 0.018Value in setProgress: 0.019Value in setProgress: 0.02Value in setProgress: 0.021Value in setProgress: 0.022Value in setProgress: 0.023Value in setProgress: 0.024Value in setProgress: 0.025Value in setProgress: 0.026Value in setProgress: 0.027Value in setProgress: 0.028Value in setProgress: 0.029
按照这样的步伐,当下一个冰河时代到来时,您的进度值将达到1,并导致PropertyChangeListener和JProgressBar发生明显变化。因此,首先,改变您的睡眠时间,并将您的大量数字更改为更合理的数字。
接下来,对重要变量进行阴影处理,尤其是JProgressBar变量progressBar。在这里声明它并在类中对其进行初始化:
public class ProgressBarTest implements PropertyChangeListener { private Jframe frame; private JButton btnRun; static JProgressBar progressBar = new JProgressBar(0, 100);附带说明一下,绝对不应声明此变量
static,但这不是当前问题的原因。原因是实际上您在初始化方法的其他地方 重新声明
了相同的变量,然后将此新对象添加到GUI中:
private void initialize() { frame = new Jframe(); // ..... JProgressBar progressBar = new JProgressBar(); // ..... frame.getContentPane().add(progressBar);请理解,这个新的progressBar变量引用了完全不同的JProgressBar,因此,如果您推进在类中创建的对象的值,则GUI将不显示任何内容,因为它显示的是完全不同的对象。为了解决这个问题,**不要在initialize方法中重新声明和初始化新变量。而是使用在类中创建的对象。
代码的其他问题:您经常使用null布局和setBounds。这将向所有人表明您是一名新手Swing程序员,因为这意味着您喜欢创建很难升级的刚性程序,并且在所有系统上看起来都不太好。而是使用布局管理器。例如,这是您的代码,其中有一些更改,所有更改都由注释指出:
import java.awt.*;import java.awt.event.*;import java.beans.*;import javax.swing.*;//!! no need to implement PropertyChangeListener//!! public class ProgressBarTest implements PropertyChangeListener {public class ProgressBarTest2 { private Jframe frame; private JButton btnRun; // !! this shouldn't be static! // !! static JProgressBar progressBar = new JProgressBar(0, 100); private JProgressBar progressBar = new JProgressBar(0, 100); // !! public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { UIManager .setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); ProgressBarTest2 window = new ProgressBarTest2(); window.frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } public ProgressBarTest2() { initialize(); } private void initialize() { frame = new Jframe(); // !!frame.setBounds(100, 100, 450, 300); frame.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); //!! frame.getContentPane().setLayout(null); //!! never use null layouts frame.setResizable(false); // !! don't create a shadowed variable // !! JProgressBar progressBar = new JProgressBar(); progressBar.setAlignmentX(Component.RIGHT_ALIGNMENT); //!! progressBar.setBounds(0, 252, 444, 20); progressBar.setStringPainted(true); //!! frame.getContentPane().add(progressBar); frame.getContentPane().add(progressBar, BorderLayout.SOUTH); btnRun = new JButton("Start Long Run"); //!! no shadowing //!! btnRun.setBounds(167, 214, 159, 31); JPanel panel = new JPanel(); //!! panel.setPreferredSize(new Dimension(450, 300)); //!! panel.setLayout(new GridBagLayout()); //!! panel.add(btnRun); //!! frame.getContentPane().add(panel, BorderLayout.CENTER); //!! btnRun.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { longRun(); } }); //!! frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } private void longRun() { //!! use a more realistic value, one that should show change in listener //!! LongRunner longRunner = new LongRunner(100000); LongRunner2 longRunner = new LongRunner2(10000); longRunner.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { int progress = (int) evt.getNewValue(); System.out.println("Value in propertyChangeListener: " + progress); progressBar.setValue(progress); } } }); longRunner.execute(); } // !! @Override // !! not needed // public void propertyChange(PropertyChangeEvent evt) { // }}class LongRunner2 extends SwingWorker<Integer, Double> { private static final long SLEEP_TIME = 15; // !! int numOfPoints; double progress; public LongRunner2(int numOfPoints) { this.numOfPoints = numOfPoints; this.progress = 0; } private void runLong(int bigNum) { for (int i = 0; i < bigNum; i++) { try { // !! quicker turn-over so that our bigNum can change // in a realistic way // !! Thread.sleep(100); Thread.sleep(SLEEP_TIME);// !! } catch (InterruptedException e) { e.printStackTrace(); } progress = (((double) i * 100) / (double) bigNum); setProgress((int) progress); // !! System.out.println("Value in setProgress: " + progress); //!! This will slow us down } } @Override protected Integer doInBackground() throws Exception { runLong(numOfPoints); return null; }}


