我正在使用swingworker()来创建发布结果的后台线程,并且应该通过process()更新GUI。但是process()永远不会被调用:
public class comm {
protected Shell shldPrinter;
private Text v1time;
private static Text cTemp1;
static boolean control1 = false;
/**
* Launch the application.
* @param args
*/
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
new comm(); //create the user interface named window
//window.open(); //invoke open() function
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Open the window.
*/
public comm() {
this.open();
}
public void open() {
Display display = Display.getDefault();
createContents();
shldPrinter.open();
shldPrinter.layout();
while (!shldPrinter.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
private void start() {
SwingWorker<Boolean,String> worker = new SwingWorker<Boolean,String> () {
//@Override
protected Boolean doInBackground() throws Exception {
while(control1) {
curtemp1++;
publish(Double.toString(curtemp1));
System.out.println(curtemp1);
try {
Thread.sleep(500); // milliseconds
} catch (InterruptedException ex) {}
}
return true;
}
protected void process(List<String> chunks) {
cTemp1.setText("chunks.get(chunks.size()-1)");
}
};
worker.execute();
}
/**
* Create contents of the window.
*/
protected void createContents() {
shldPrinter = new Shell();
shldPrinter.setSize(490, 299);
shldPrinter.setText("Robogel Temp Control");
final Button btnCln1 = new Button(shldPrinter, SWT.CHECK);
btnCln1.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
control1 = btnCln1.getSelection();
if(control1)
start();
}
});
btnCln1.setBounds(22, 51, 69, 16);
btnCln1.setText("Valve 1");
//create text box for valve 1 timing
v1time = new Text(shldPrinter, SWT.BORDER | SWT.CENTER);
v1time.addFocusListener(new FocusAdapter() {
@Override
//when cursor moves away from text box
public void focusLost(FocusEvent e) {
reftemp1 = Double.parseDouble(v1time.getText()); // get time in ascii format and convert it into int
}
});
v1time.setText("25");
v1time.setBounds(97, 49, 51, 21);
cTemp1 = new Text(shldPrinter, SWT.BORDER | SWT.CENTER);
cTemp1.setEditable(false);
cTemp1.setText(Double.toString(curtemp1));
cTemp1.setBounds(203, 49, 51, 21);
}
}
当GUI关闭时,会出现以下错误:
Exception in thread "AWT-EventQueue-0" org.eclipse.swt.SWTException: Widget is disposed
at org.eclipse.swt.SWT.error(SWT.java:4397)
at org.eclipse.swt.SWT.error(SWT.java:4312)
at org.eclipse.swt.SWT.error(SWT.java:4283)
at org.eclipse.swt.widgets.Widget.error(Widget.java:472)
at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:344)
at org.eclipse.swt.widgets.Text.setText(Text.java:2240)
at comm$2.process(comm.java:172)
at javax.swing.SwingWorker$3.run(Unknown Source)
at sun.swing.AccumulativeRunnable.run(Unknown Source)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(Unknown Source)
at sun.swing.AccumulativeRunnable.run(Unknown Source)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(Unknown Source)
at javax.swing.Timer.fireActionPerformed(Unknown Source)
at javax.swing.Timer$DoPostEvent.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
我已经阅读了很多论坛,但没有任何帮助。尝试过调用done(),但即使这样也不会被调用。
答案 0 :(得分:1)
混合Swing EDT和SWT线程。这将导致异常,因为SWT会检查每次调用是否在SWT线程中进行。从您的代码中删除:Swing
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
new comm(); //create the user interface named window
//window.open(); //invoke open() function
} catch (Exception e) {
e.printStackTrace();
}
}
});
你只需要在秋千环境中使用它,因为swing会启动EDT。在SWT中,创建Display的线程将是EDT。新版本:
new comm(); //create the user interface named window
现在要在后台执行一些东西,你可以使用通常的java机制(并发等),但是不要使用Swing的东西,它只会让你变得非常复杂。重要的是,在后台工作完成后,您使用Display#asyncExec同步回SWT EDT这里是example
我建议在没有任何摆码的情况下重写你的例子,并在新问题中重新发布任何问题。 (非常奇怪的事情正在发生,从我的角度来看很难说出问题是什么。)
答案 1 :(得分:0)
SwingWorker#process()
方法完成时才调用 doInBackground
。我看到,control1
永远不会false
,所以doInBackground
永远不会完成。尽量使用javax.swing.Timer
代替SwingWorker
:
Timer = new Timer(500, new ActionListener() {
long curtemp1 = 0;
@Override
public void actionPerfomed(ActionEvent e) {
cTemp1.setText(String.valueOf(curtemp1));
curtemp1++;
}
});