我有主GUI线程,其中有一个JprogressBar,并且正在实现ProprtyChangeListener。
当按下按钮时,扩展SwingWorker的其他类将开始执行并执行一系列可能很长的计算。我需要A类中的进度条以根据B类中的变量来呈现进度。
我的代码在下面(我所有失败的尝试都可能有点混乱…)
将不胜感激。
GUI类别:
SignalSimulator signalSimulator = new SignalSimulator(
path, numOfdataPoints, numOfLocalSpikes,
numOfExpSpikes, noiseAmp, slope, offset,
rdbtnSineWave.isSelected());
signalSimulator.addPropertyChangeListener( new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
String property = evt.getPropertyName();
if ("progress".equals(property)) {
int progress = (Integer) evt.getNewValue();
System.out.println("value in PropertChangeListener is: " + progress);
progressBar.setValue(progress);
}
}
});
signalSimulator.execute();
计算类:
protected Integer doInBackground() throws Exception {
if (isSine){
data = generateSineWave(numOfDataPoints, noiseAmp, offset);
data = addAnomalies(data, numOfPointOutliers, numOfExpSpikes);
} else {
data = generateLinearSignal(numOfDataPoints, noiseAmp, slope, offset);
data = addAnomalies(data, numOfPointOutliers, numOfExpSpikes);
}
writeLogFile(path, ".txt", data);
firePropertyChange("progress", 1, 1);
setProgress((int)progress);
publish(progress);
System.out.println("value in doInBackground is: " + progress);
return 1;
}
编辑
原始问题仍然存在。出于某种原因,进度条仍然没有更新,我可以肯定ProgressBar.setValue(progress)中的“
progress”变量正在更新,但GUI中的进度条保持不变(固定为0),这是我的新代码:
GUI类:
SignalSimulator signalSimulator = new SignalSimulator(path, numOfdataPoints, numOfLocalSpikes, numOfExpSpikes, noiseAmp, slope, offset, rdbtnSineWave.isSelected());
signalSimulator.addPropertyChangeListener( new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
String property = evt.getPropertyName();
if ("progress".equals(property)) {
int progress = (Integer) evt.getNewValue();
System.out.println("value in PropertChangeListener is: " + progress);
progressBar.setValue(progress);
}
}
});
signalSimulator.execute();
SwingWorker类:
@Override
protected Integer doInBackground() throws Exception {
if (isSine){
data = generateSineWave(numOfDataPoints, noiseAmp, offset);
data = addAnomalies(data, numOfPointOutliers, numOfExpSpikes);
}
else{
data = generateLinearSignal(numOfDataPoints, noiseAmp, slope, offset);
data = addAnomalies(data, numOfPointOutliers, numOfExpSpikes);
}
writeLogFile(path, ".txt", data);
return 1;}
public double[] generateSineWave(int numOfDataPoints, double noiseAmp, double offset){
Random rnd = new Random();
double[] dataArray = new double[numOfDataPoints];
for (int i=0;i<numOfDataPoints;i++){
dataArray[i] = Math.sin(Math.toRadians(i))+rnd.nextDouble()*noiseAmp+offset;
progress = ((double)i)/(double)numOfDataPoints*100;
//firePropertyChange("progress", 1, 1);
setProgress((int)progress);
//publish(progress);
System.out.println("value in doInBackground is: " + progress);
}
return dataArray;
编辑 重写整个内容,而无需额外的(不相关的)代码。我想我在这里缺少一些基本的东西,因为它仍然无法更新进度条。
public class ProgressBarTest implements PropertyChangeListener {
private JFrame frame;
private JButton btnRun;
static 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.nimbus.NimbusLookAndFeel");
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
ProgressBarTest window = new ProgressBarTest();
window.frame.setVisible(true);
//SignalSimulator signalSimulator = new SignalSimulator();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public ProgressBarTest() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
frame.setResizable(false);
JProgressBar progressBar = new JProgressBar();
progressBar.setAlignmentX(Component.RIGHT_ALIGNMENT);
progressBar.setBounds(0, 252, 444, 20);
progressBar.setStringPainted(true);
frame.getContentPane().add(progressBar);
JButton btnRun = new JButton("Start Long Run");
btnRun.setBounds(167, 214, 159, 31);
frame.getContentPane().add(btnRun);
btnRun.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
longRun();
}
} );
}
private void longRun(){
LongRunner longRunner = new LongRunner(100000);
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
public void propertyChange(PropertyChangeEvent arg0) {
// TODO Auto-generated method stub
}
}
和SwingWorker:
import javax.swing.SwingWorker;
public class LongRunner extends SwingWorker<Integer, Double>{
int numOfPoints;
double progress;
public LongRunner(int numOfPoints) {
this.numOfPoints = numOfPoints;
this.progress = 0;
}
private void runLong(int bigNum){
for (int i=0; i< bigNum; i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
progress = (((double)i*100)/(double)bigNum);
setProgress((int)progress);
System.out.println("Value in setProgress: "+progress);
}
}
@Override
protected Integer doInBackground() throws Exception {
runLong(numOfPoints);
return null;
}
}
我在这里做错了什么?
您是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 selected
data = 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.0
Value in setProgress: 0.001
Value in setProgress: 0.002
Value in setProgress: 0.003
Value in setProgress: 0.004
Value in setProgress: 0.005
Value in setProgress: 0.006
Value in setProgress: 0.007
Value in setProgress: 0.008
Value in setProgress: 0.009
Value in setProgress: 0.01
Value in setProgress: 0.011
Value in setProgress: 0.012
Value in setProgress: 0.013
Value in setProgress: 0.014
Value in setProgress: 0.015
Value in setProgress: 0.016
Value in setProgress: 0.017
Value in setProgress: 0.018
Value in setProgress: 0.019
Value in setProgress: 0.02
Value in setProgress: 0.021
Value in setProgress: 0.022
Value in setProgress: 0.023
Value in setProgress: 0.024
Value in setProgress: 0.025
Value in setProgress: 0.026
Value in setProgress: 0.027
Value in setProgress: 0.028
Value 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;
}
}
我需要将给定的任何图像转换为字节数组,以满足加密要求。我正在使用JProgressBar监控所选图像较大时的转换进度: 我定义了一个类,它使用,如下所示: 不幸的是,这个错误发生了! 我不知道我的代码出了什么问题!在写这段代码之前,我读了和,但我觉得我遗漏了什么!我能得到一个有用的提示吗。 谢谢:)
问题内容: 我无法更新进度条…这是我的代码 进度栏状态仅在线程末尾更新。有人能帮我吗?? 问题答案: 谢谢大家 我这样解决了
主类:
我将primefaces 3.3与JSF 2.1结合使用。在下面的代码中,我有一个primeFaces dataTable,其中包含从数据库中提取的数据行,该数据库通过页面左侧的树组件正确激活。dataTable显示和行为正确。我有一个名为“更新”的删除功能,它刷新我的数据表,并在数据库更新后反映我的更改。我的问题是f:facet(id=“header”)。该方面包含一个commandLink,它
问题内容: 我正在尝试将JProgressBar添加到我的程序中,但不会更新!仅当原因为100%时,该值才会更改。这是我的方法。 更改进度栏的值位于上述方法的底部。 这就是我所谓的方法。 编辑:以上根本不是问题,问题之一是程序正在使用整数除法而不是十进制。 问题答案: 是一个整数,也是。因此发生的是小数被截断。你应该做什么,就像 这样做是确保将其除以具有十进制功能的数据类型,该数据类型将返回更具包
我有一个以下格式的日期,我需要解析它,并转换成一个纪元时间。 关于我做错了什么有什么帮助吗?