从另一个线程更新SWT对象

在我的Java应用程序中,当调用主模块时,我在一个单独的线程中启动我的SWT GUI。 我需要在主线程中执行一些长操作并更新GUI线程。 当我尝试从主线程更新GUI线程,即更改标签文本或其他东西时,我得到一个java.lang.NullPointerException 。 从我在网上看到的是因为SWT不允许非UI线程更新UI对象。 如何从主线程更新GUI线程。

我在网上找到了一些例子,但它们都处理了GUI在主线程中运行的情况,而长操作则在单独的线程中。 我的情况完全相反。

有人能告诉我如何更新GUI线程中的小部件吗?

我认为您正在获取java.lang.NullPointerException因为您在创建GUI组件之前尝试访问它。 理想情况下,您应该等待gui组件被创建…例如……

我在一个单独的线程中创建一个GUI …就像这样

 package test; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; public class GUIThread implements Runnable { private Display display; private Label label; public Display getDisplay(){ return display; } public void run() { display = new Display(); Shell shell = new Shell(display); shell.setLayout(new GridLayout()); shell.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,false)); label = new Label(shell,SWT.NONE); label.setText(" -- "); shell.open(); shell.pack(); while (!shell.isDisposed()) { if (!display.readAndDispatch ()) display.sleep (); } display.dispose(); } public synchronized void update(final int value) { if (display == null || display.isDisposed()) return; display.asyncExec(new Runnable() { public void run() { label.setText(""+value); } }); } } 

在我的主要方法中,我做这样的事情….

 package test; import org.eclipse.swt.widgets.Display; public class Main { public static void main(String[] args) throws Exception { final GUIThread gui = new GUIThread(); Thread t = new Thread(gui); t.start(); Thread.sleep(3000); // POINT OF FOCUS Display d = gui.getDisplay(); for(int i = 0; i<100; i++) { System.out.println(i + " " + d); gui.update(i); Thread.sleep(500); } } } 

现在,如果我们在上面的代码中注释出POINT OF FOCUS ,那么我将总是得到NullPointerException ......但是3秒的延迟使我的GUI线程有足够的时间处于就绪状态,因此它不会通过NullPointerException ...... ..

在这种情况下你必须有效地使用waityield方法......否则会导致“难以找到错误”...即等待UI正确实例化然后产生...

实际处理也是在主线程中完成的,GUI在单独的线程中运行...正确通信最好有一些共享和同步的数据结构...或者可以使用套接字通信完成...你的主线程填充一些port和你的GUI线程asynchronously监听该端口....

希望这会通过你的问题的一些亮点....

简而言之,SWT是一个单线程UI工具包。 因此,必须在SWT事件线程中更新窗口小部件,就像在Swing中一样。 因此,您必须使用匿名Runnable类调用刷新:

 Display.getDefault().asyncExec(new Runnable() { public void run() { someSwtLabel.setText("Complete!"); } }); 

对于更长的解释,这篇JavaLobby文章是对这种线程使用模型的一个很好的介绍。