[英]How to deliver object to a long-running SwingWorker from the EDT?
How can the EDT communicate to an executing SwingWorker
? EDT 如何与正在执行的
SwingWorker
通信? There a lot of ways for the SwingWorker
to communicate information back to the EDT - like publish/process and property changes but no defined way (that I have seen) to communicate in the other direction. SwingWorker
有很多方法可以将信息传回 EDT——比如发布/处理和属性更改,但没有定义的方式(我见过)在另一个方向上进行通信。 Seems like good old Java concurrent inter-thread communication would be the way to go via wait()
and notify()
.似乎旧的 Java 并发线程间通信将是通过
wait()
和notify()
到 go 的方式。 This doesn't work.这行不通。 I'll explain later.
我稍后会解释。 I actually got it to work but it uses an ugly polling mechanism.
我实际上让它工作,但它使用了一个丑陋的轮询机制。 I feel like there should be a better way.
我觉得应该有更好的方法。 Here is the process that I am trying to accomplish:
这是我要完成的过程:
Swing
UI (EDT) a user starts a SwingWorker
long-running task (the engine).Swing
UI (EDT) 启动SwingWorker
长时间运行的任务(引擎)。Swing
button.Swing
按钮。 The problem I have with wait()
/ notify()
is that in step 3 any invocation of wait()
in doInBackground()
causes the done()
method to be immediately fired and the SwingWorker
to be terminated.我对
wait()
/ notify()
的问题是,在第 3 步中, doInBackground()
中对wait()
的任何调用都会导致done()
方法立即被触发并终止SwingWorker
。 I was able to get the above process to work by using an ugly sleep()
loop in doInBackground()
:通过在
doInBackground()
中使用丑陋的sleep()
循环,我能够使上述过程正常工作:
for (;;)
{
Thread.sleep(10);
if (fromEDT != null)
{
// Process the update from the EDT
System.out.println("From EDT: " + fromEDT);
fromEDT = null;
break;
}
}
What this really is that in step 5 the engine wakes itself up and checks for updates from the EDT.这实际上是在第 5 步中引擎将自己唤醒并检查来自 EDT 的更新。
Is this the best way to do this?这是最好的方法吗? I kind of doubt it.
我有点怀疑。
The following is an mre demonstrating a SwingWorker
paused and waiting for user's input:以下是一个演示
SwingWorker
已暂停并等待用户输入的 mre:
import java.awt.*;
import java.util.List;
import javax.swing.*;
public class SwingWorkerWaitDemo {
public static void creategui(){
JFrame f = new JFrame("SwingWorker wait Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
f.add(new MainPanel());
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
creategui();
}
}
class MainPanel extends JPanel {
private static final String BLANK = " ";
private MyWorker swingWorker;
private final JLabel output, msg;
private final JButton start, stop, respond;
MainPanel() {
setLayout(new BorderLayout(2, 2));
start = new JButton("Start");
start.addActionListener(e->start());
stop = new JButton("Stop");
stop.setEnabled(false);
stop.addActionListener(e->stop());
JPanel ssPane = new JPanel(new FlowLayout(FlowLayout.CENTER));
ssPane.add(start); ssPane.add(stop);
add(ssPane, BorderLayout.PAGE_START);
output = new JLabel(BLANK);
JPanel outputPane = new JPanel(new FlowLayout(FlowLayout.CENTER));
outputPane.add(output);
add(outputPane, BorderLayout.CENTER);
msg = new JLabel(BLANK);
respond = new JButton("Respond");
respond.addActionListener(e->respond());
respond.setEnabled(false);
JPanel responsePane = new JPanel();
responsePane.add(msg); responsePane.add(respond);
add(responsePane, BorderLayout.PAGE_END);
}
@Override
public Dimension getPreferredSize(){
return new Dimension(400, 200);
}
private void start() {
start.setEnabled(false);
stop.setEnabled(true);
swingWorker = new MyWorker();
swingWorker.execute();
}
private void stop() {
stop.setEnabled(false);
swingWorker.setStop(true);
}
private void message(String s){
msg.setText(s);
}
private void clearMessage(){
msg.setText(BLANK);
}
private void askForUserResponse(){
respond.setEnabled(true);
message("Please respond " );
}
private void respond(){
clearMessage();
respond.setEnabled(false);
swingWorker.setPause(false);
}
class MyWorker extends SwingWorker<Integer, Integer> {
private boolean stop = false;
private volatile boolean pause = false;
@Override
protected Integer doInBackground() throws Exception {
int counter = 0;
while(! stop){
publish(counter++);
if(counter%10 == 0) {
pause = true;
askForUserResponse();
while(pause){ /*wait*/ }
}
Thread.sleep(500);
}
return counter;
}
@Override
protected void process(List<Integer> chunks) {
for (int i : chunks) {
output.setText(String.valueOf(i));
}
}
@Override
protected void done() {
message("All done");
}
void setStop(boolean stop) {
this.stop = stop;
}
void setPause(boolean pause) {
this.pause = pause;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.