SWT无效的线程访问 - 混合显示Draw2D

时间:2014-07-29 17:18:35

标签: java multithreading user-interface swt draw2d

我有一个使用Zest显示图形的类,它可以自己运行,因为它有一个main方法。但是,当我在另一个shell中选择一个按钮时,我想要运行该主要方法。问题是当我从按钮的selectionListener调用main函数时,我得到一个无效的线程访问SWTException。根据我的理解,两种情况下使用的Display对象都会造成麻烦。看看这里的类似帖子也没有帮助我。有人可以指出我正确的方向吗?谢谢。 *我添加了简短的可测试代码来说明我的问题。 import org.eclipse.swt.widgets.Display;

public class CallGraph {

    protected Shell shell;

    /**
     * Launch the application.
     * @param args
     */
    public static void main(String[] args) {
        try {
            CallGraph window = new CallGraph();
            window.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Open the window.
     */
    public void open() {
        Display display = Display.getDefault();
        createContents();
        shell.open();
        shell.layout();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    /**
     * Create contents of the window.
     */
    protected void createContents() {
        shell = new Shell();
        shell.setSize(450, 300);
        shell.setText("SWT Application");
        shell.setLayout(new GridLayout(6, false));
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);
        new Label(shell, SWT.NONE);

        Button btnGetGraph = new Button(shell, SWT.NONE);
        btnGetGraph.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                RadialLayoutExample.main(null);
            }
        });
        btnGetGraph.setText("Get Graph");

    }

}

下面的类有按钮来调用上面的主要方法。

import org.eclipse.swt.SWT;


import org.eclipse.swt.layout.FillLayout;

import org.eclipse.swt.widgets.Display;

import org.eclipse.swt.widgets.Shell;

import org.eclipse.zest.core.widgets.Graph;

import org.eclipse.zest.core.widgets.GraphConnection;

import org.eclipse.zest.core.widgets.GraphNode;

//import org.eclipse.zest.layout.algorithms.RadialLayoutAlgorithm;

//import org.eclipse.zest.layout.interfaces.LayoutAlgorithm;



public class RadialLayoutExample {

        public static void main(String[] args) {

                // Create the shell

                Display d = new Display();

                Shell shell = new Shell(d);

                shell.setText("GraphSnippet1");

                shell.setLayout(new FillLayout());

                shell.setSize(500, 500);



                final Graph g = new Graph(shell, SWT.NONE);

                g.setSize(500, 500);

                GraphNode root = new GraphNode(g, SWT.NONE, "Root");

                for (int i = 0; i < 3; i++) {

                        GraphNode n = new GraphNode(g, SWT.NONE, "1 - " + i);

                        for (int j = 0; j < 3; j++) {

                                GraphNode n2 = new GraphNode(g, SWT.NONE, "2 - " + j);

                                new GraphConnection(g, SWT.NONE, n, n2).setWeight(-1);

                        }

                        new GraphConnection(g, SWT.NONE, root, n);





                //final org.eclipse.zest.layouts.algorithms.RadialLayoutAlgorithm layoutAlgorithm = new org.eclipse.zest.layouts.algorithms.RadialLayoutAlgorithm();
                final org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm layoutAlgorithm = new org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm();


                g.setLayoutAlgorithm(layoutAlgorithm, true);

                shell.open();

                while (!shell.isDisposed()) {

                        while (!d.readAndDispatch()) {

                                d.sleep();

                        }

                }

        }

}
}

1 个答案:

答案 0 :(得分:0)

将main方法接收的参数的数据类型从String更改为Display。调用main方法时,将现有类的显示作为参数传递。这背后的原因是,对于每个应用程序,只需要一个Display对象,因为它充当应用程序和底层操作系统之间的链接。使用涉及的线程创建多个混乱。 *感谢@ greg-449的评论,指出我正确的方向。