java - SwingWorker 在 EDT 线程中调用 Thread.sleep() 时不会 运行
java - SwingWorker doens't run when calling Thread.sleep() in EDT thread
我正在尝试创建一个程序来求解二次方程并计算求解时间。我有 JButton,当我点击它时,计算就会开始。我的 SwingWorker 是用来计时的,它会每 1 秒更新一次时间。因为计算很快,我在 JButton actionPerformed 中调用 Thread.sleep() 所以我可以看到 SwingWorker 计算时间,但是当我在 EDT 线程中调用 Thread.sleep(3000) 时,SwingWorker 不工作但等待方程求解完成打印出运行 time = 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>");
}
}
我现在找到了解决办法,我把定时器和计算代码放在同一个线程里class:
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();
}
My SwingWorker is for counting time, it will update time every 1 second.
如果这个工作人员的唯一职责是用经过的时间更新标签,那么 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();
}
我正在尝试创建一个程序来求解二次方程并计算求解时间。我有 JButton,当我点击它时,计算就会开始。我的 SwingWorker 是用来计时的,它会每 1 秒更新一次时间。因为计算很快,我在 JButton actionPerformed 中调用 Thread.sleep() 所以我可以看到 SwingWorker 计算时间,但是当我在 EDT 线程中调用 Thread.sleep(3000) 时,SwingWorker 不工作但等待方程求解完成打印出运行 time = 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>");
}
}
我现在找到了解决办法,我把定时器和计算代码放在同一个线程里class:
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();
}
My SwingWorker is for counting time, it will update time every 1 second.
如果这个工作人员的唯一职责是用经过的时间更新标签,那么 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();
}