我正在尝试创建一个程序来求解二次方程式并计算求解时间。我有JButton,当我单击它时,计算将开始。我的SwingWorker用于计时,它将每1秒更新一次时间。因为计算速度很快,所以我在JButton actionPerformed中调用Thread.sleep(),这样我就可以看到SwingWorker的计时时间,但是当我在EDT线程中调用Thread.sleep(3000)时,SwingWorker不起作用,但是等到等式求解完毕完成打印输出运行时间= 3s。我该如何解决这个问题,以便SwingWorker将每1秒更新一次时间,而不是仅打印3秒。
//SwingWorker for counting time
public class Worker extends SwingWorker<Integer, Long> {
private JLabel label;
public Worker(JLabel label) {
this.label = label;
}
@Override
protected Integer doInBackground() throws Exception {
long i = System.currentTimeMillis();
Timer SimpleTimer = new Timer(10, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
publish(System.currentTimeMillis() - i);
}
});
SimpleTimer.start();
return 1;
}
protected void process(List<Long> chunks) {
for(long i : chunks) {
label.setText("" + i);
}
}
}
//Solving quadratic function in JButton actionPerformed
private void solveActionPerformed(java.awt.event.ActionEvent evt) {
int a, b, c;
double x1, x2;
int i = 0;
try {
a = Integer.parseInt(inputA.getText());
b = Integer.parseInt(inputB.getText());
c = Integer.parseInt(inputC.getText());
} catch (Exception e) {
JOptionPane.showMessageDialog(this, "Re-enter.");
return;
}
Worker worker = new Worker(clock);
worker.execute();
try {
Thread.sleep(3000);
} catch (Exception e) {
}
double delta = b * b - 4 * a * c;
if(delta < 0) {
result.setText(".");
} else if(delta == 0) {
result.setText("x1 = x2 = " + -b / 2 * a);
} else {
x1 = (-b + Math.sqrt(delta)) / (2 * a);
x2 = (-b - Math.sqrt(delta)) / (2 * a);
result.setText("<html>x1 = " + x1 + "<br>x2 = " + x2 + "</html>");
}
}
我现在找到了解决方案,我将计时器和计算代码放在同一个线程类中:
public class NewThread implements Runnable {
private JLabel label, result;
private int a, b, c;
public NewThread(JLabel label, int a, int b, int c, JLabel result) {
this.label = label;
this.a = a;
this.b = b;
this.c = c;
this.result = result;
}
@Override
public void run() {
double x1, x2;
long i = System.currentTimeMillis();
Timer timer = new Timer(10, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
label.setText("Thoi gian tinh toan: " + (Math.round(System.currentTimeMillis() - i) / 1000) + " giay");
}
});
timer.start();
try {
Thread.sleep(3000);
} catch (Exception e) {
}
double delta = b * b - 4 * a * c;
if(delta < 0) {
result.setText("Phuong trinh vo nghiem.");
} else if(delta == 0) {
result.setText("Phuong trinh co nghiem kep x1 = x2 = " + -b / 2 * a);
} else {
x1 = (-b + Math.sqrt(delta)) / (2 * a);
x2 = (-b - Math.sqrt(delta)) / (2 * a);
result.setText("<html>Phuong co 2 nghiem.<br>x1 = " + x1 + "<br>x2 = " + x2 + "</html>");
}
timer.stop();
}
答案 0 :(得分:1)
我的SwingWorker用于计时,它将每1秒更新一次。
如果此工作人员的唯一责任是使用经过的时间来更新标签,那么Swing Timer是一个更好的选择。让SwingWorker doInBackground()
实现进行繁重的计算,最后done()
实现可能只是停止计时器并显示最终结果。
请勿在EDT中调用Thread.sleep()
,因为它将冻结整个GUI事件处理,并且您可能只会看到最终结果而没有预期的定期更新。
仅添加一个简单的代码段开头:
public void startCalculation() {
Timer timer = new Timer(1000, new ActionListener() {
AtomicInteger elapsedSeconds = new AtomicInteger();
@Override
public void actionPerformed(ActionEvent evt) {
label.setText(String.format("Elapsed time: %d seconds", elapsedSeconds.incrementAndGet()));
}
});
SwingWorker<Integer, Void> worker = new SwingWorker<Integer, Void>() {
@Override
protected Integer doInBackground() throws Exception {
// do heavy stuff
Thread.sleep(3000); // it is safe to "sleep" here because it's not executed in the EDT
return 1;
}
@Override
protected void done() {
timer.stop();
// update the GUI with the results here if it's required
}
};
timer.start();
worker.execute();
}