从另一个线程更新SWT对象

发布于 2021-01-29 19:41:05

在我的Java应用程序中,当调用主模块时,我在单独的线程中启动SWT
GUI。我需要在主线程中执行一些长时间的操作并更新GUI线程。当我尝试从主线程更新GUI线程(即更改标签文本等)时,出现了java.lang.NullPointerException。根据我在线阅读的内容,因为SWT不允许非UI线程更新UI对象。如何从主线程更新GUI线程。

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

有人可以告诉我如何在GUI线程中更新小部件吗?

关注者
0
被浏览
123
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    我认为您正在获得,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.....

    在这种情况下,您必须有效地使用waitand yield方法…否则将导致“很难找到错误” …即等待UI正确实例化然后屈服…

    同样,实际的处理是在主线程中完成的,并且GUI在单独的线程中运行…要正确通信,最好具有一些共享和同步的数据结构…或者可以使用套接字通信来完成…主线程填充一些,port并且您的GUI线程asynchronously正在该端口上侦听。

    希望这可以通过您的问题得到一些启示。



推荐阅读
知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看