从非UI线程访问UI线程

时间:2012-10-07 15:56:12

标签: java swt eclipse-rcp jface

我正在尝试将剪贴板的内容复制到文本框,但我收到了“无效的线程访问”消息。

我在剪贴板上使用了一个监听器,如果有一些变化,会通知我。

我创建了一个新线程来包装侦听器,但它似乎无法正常工作。

这是代码:

    public class ClipboardDialog extends TitleAreaDialog {

    // Local attributs
    private Text mTextClipboardcontent;


    public ClipboardDialog (Shell parentShell) {

        super(parentShell);

    }


    @Override
    protected Control createDialogArea(Composite parent) {

        // Creating display and controls

        setTitle("ClipBoard content");
        Composite area = (Composite) super.createDialogArea(parent);
        Composite container = new Composite(area, SWT.NONE);
        container.setLayout(new FormLayout());
        GridData gd_container = new GridData(GridData.FILL_HORIZONTAL);
        // gd_container.grabExcessVerticalSpace = true;
        gd_container.horizontalAlignment = SWT.LEFT;
        gd_container.verticalAlignment = SWT.TOP;
        container.setLayoutData(gd_container);

        // Group control
        Group grpInputData = new Group(container, SWT.NONE);
        FormData fd_grpInputData = new FormData();
        fd_grpInputData.bottom = new FormAttachment(0, 303);
        fd_grpInputData.right = new FormAttachment(0, 467);
        fd_grpInputData.top = new FormAttachment(0, 5);
        fd_grpInputData.left = new FormAttachment(0, 5);
        grpInputData.setLayoutData(fd_grpInputData);
        grpInputData.setText("Input Data");
        GridLayout gl_grpInputData = new GridLayout(4, false);
        gl_grpInputData.marginLeft = 4;
        gl_grpInputData.marginHeight = 0;
        gl_grpInputData.marginWidth = 2;
        gl_grpInputData.verticalSpacing = 10;
        gl_grpInputData.horizontalSpacing = 10;
        grpInputData.setLayout(gl_grpInputData);
        new Label(grpInputData, SWT.NONE);
        new Label(grpInputData, SWT.NONE);
        new Label(grpInputData, SWT.NONE);
        new Label(grpInputData, SWT.NONE);
        new Label(grpInputData, SWT.NONE);


        // Input control
        mTextClipboardcontent = new Text(grpInputData, SWT.BORDER);
        GridData gdContent = new GridData(SWT.LEFT, SWT.TOP, false, false, 1,
                1);
        gdContent.heightHint = 18;
        gdContent.widthHint = 250;
        mTextClipboardcontent.setLayoutData(gdContent);
        mTextClipboardcontent.setBounds(0, 0, 76, 21);
        mTextClipboardcontent.setTextLimit(8);



        new Thread(new Runnable() {
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                    }
                    Display.getDefault().syncExec(new Runnable() {
                        public void run() {

                            Toolkit.getDefaultToolkit().getSystemClipboard()
                                    .addFlavorListener(new FlavorListener() {

                                        @Override
                                        public void flavorsChanged(FlavorEvent e) {

                                            String result = "";
                                            Clipboard clipboard = Toolkit
                                                    .getDefaultToolkit()
                                                    .getSystemClipboard();

                                            Transferable contents = clipboard
                                                    .getContents(null);
                                            boolean hasTransferableText = (contents != null)
                                                    && contents
                                                            .isDataFlavorSupported(DataFlavor.stringFlavor);

                                            if (hasTransferableText) {

                                                try {

                                                    // Getting the content of
                                                    // the ClipBoard
                                                    result = (String) contents
                                                            .getTransferData(DataFlavor.stringFlavor);

                                                    mTextContent.settext(result);
                                                } catch (UnsupportedFlavorException ex) {

                                                    // Loggin the exception
                                                    Log.LogError(
                                                            ex.getClass()
                                                                    .getCanonicalName(),
                                                            ex.getMessage());

                                                } catch (IOException ex) {


                                                    // Loggin the exception
                                                    Log.LogError(
                                                            ex.getClass()
                                                                    .getCanonicalName(),
                                                            ex.getMessage());
                                                }

                                            }
                                        }
                                    });

                        }
                    });
                }
            }
        }).start();

        return area;
    }

    /**
     * Create contents of the button bar.
     * 
     * @param parent
     */
    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        Button mBtnOK = createButton(parent, IDialogConstants.OK_ID,
                IDialogConstants.OK_LABEL, true);
        mBtnOK.setEnabled(false);
        createButton(parent, IDialogConstants.CANCEL_ID,
                IDialogConstants.CANCEL_LABEL, false);
    }

    /**
     * Return the initial size of the dialog.
     */
    @Override
    protected Point getInitialSize() {
        return new Point(479, 400);
    }
}

1 个答案:

答案 0 :(得分:4)

在一个不是UI线程的线程中调用您的flavor侦听器。

您需要使用Runnable(或Display,根据需要)传递给asyncExec syncExec执行其代码:

Toolkit.getDefaultToolkit().getSystemClipboard().addFlavorListener(
    new FlavorListener() {

    @Override
     public void flavorsChanged(FlavorEvent e) {
         Display.getDefault().asyncExec(new Runnable(){
            public void run(){
              // do things on the UI thread
              String result = "";
              Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
              Transferable contents = clipboard.getContents(null);
              ...
            }
         }
     });

runnable将在UI线程上执行,从而避免您的错误。

请注意,您可能不需要在UI线程中执行此操作:

 Toolkit.getDefaultToolkit().getSystemClipboard()
                                    .addFlavorListener(