【问题标题】:Mixing frames from SWT and Swing (JFrame)混合来自 SWT 和 Swing (JFrame) 的帧
【发布时间】:2016-10-26 05:19:43
【问题描述】:

我收到了大量基于 JFrame 的小型窗口,这些窗口最初用作单独的微应用程序。所以每个都有自己的 main 方法,其中 Runnable 被添加到 EventQueue 中。

我应该将它与 SWT Main-Frame 应用程序合并,以便用户可以调用任何单独的基于 Swing 的微应用程序。所以最终将是拥有一个调用各个 JFrame 子应用程序的顶级 Frame SWT。我知道这不是正确构建 GUI 应用程序的方式,但这是我被赋予的任务。

  1. 当 SWT 是主要项目并且它调用多个基于 Swing 的 JFrame 时,一切正常(您可以尝试运行 SWTApp.Main)。看来我的任务并没有我最初想的那么困难。

2。我试图更多地玩这个,我做了相反的事情。当您运行 SwingApp.main 时,它允许您运行多个 SWT 子应用程序。我很惊讶地看到 SWT 在完成后不喜欢被调用。它产生了以下错误:

org.eclipse.swt.SWTException:线程访问无效 org.eclipse.swt.SWT.error(SWT.java:4533) 在 org.eclipse.swt.SWT.error(SWT.java:4448) 在 org.eclipse.swt.SWT.error(SWT.java:4419) 在 org.eclipse.swt.widgets.Widget.error(Widget.java:482) 在 org.eclipse.swt.widgets.Shell.(Shell.java:286) 在 org.eclipse.swt.widgets.Shell.(Shell.java:277) 在 org.eclipse.swt.widgets.Shell.(Shell.java:226) 在 org.eclipse.swt.widgets.Shell.(Shell.java:160) 在 com.stackoverflow.SWTApp.createContents(SWTApp.java:46) 在 com.stackoverflow.SWTApp.open(SWTApp.java:32) 在 com.stackoverflow.SWTApp.main(SWTApp.java:21) 在 com.stackoverflow.SwingApp$2$1.run(SwingApp.java:48) 在 java.lang.Thread.run(Thread.java:745)

尽管这不是我最终应用程序的目标 - 我想知道为什么会这样以及如何解决 SWT 的问题。似乎 SWT 在它的一些单例中留下了一些痕迹,所以它知道它已经执行并且不能再次重新运行。任何想法如何解决它?

package com.stackoverflow;

import java.awt.EventQueue;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class SwingApp extends javax.swing.JFrame {

    private JPanel contentPane;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                SwingApp frame = new SwingApp();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

    }

    /**
     * Create the frame.
     */
    public SwingApp() {
        setTitle("Swing");
        setDefaultCloseOperation(SwingApp.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        //contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JButton startSWTApp = new JButton("Start SWT");
          startSWTApp.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                new Thread(new Runnable() {
                    public void run() {
                        SWTApp.main(null);
                    }
                }).start();;

            }
        });

        startSWTApp.setBounds(34, 26, 97, 25);
        contentPane.add(startSWTApp);

        JButton btnClose = new JButton("Close");
        btnClose.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                SwingApp.this.dispose();
            }
        });
        btnClose.setBounds(34, 124, 97, 25);
        contentPane.add(btnClose);
    }
}

以及基于 Swing 的单个 JFrame(此处简化):

package com.stackoverflow;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;

public class SWTApp {

    protected Shell shell;

    /**
     * Launch the application.
     * @param args
     */
    public static void main(String[] args) {
        try {
            SWTApp window = new SWTApp();
            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");

        Button btnCloseSwtApp = new Button(shell, SWT.NONE);
        btnCloseSwtApp.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                    shell.dispose();
            }
        });
        btnCloseSwtApp.setBounds(56, 78, 126, 30);
        btnCloseSwtApp.setText("Close SWT App.");

        Button btnSwingApp = new Button(shell, SWT.NONE);
        btnSwingApp.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                new Thread(new Runnable() {
                    public void run() {
                        SwingApp.main(null);
                    }}).start();

            }
        });
        btnSwingApp.setText("Open Swing App");
        btnSwingApp.setBounds(56, 156, 126, 30);

    }
}

【问题讨论】:

    标签: java swing user-interface jframe swt


    【解决方案1】:

    在没有创建显示时调用Display.getDefault() 会将当前线程建立为 SWT 用户界面线程。该线程保持不变,直到显示关闭。在任何其他线程上执行 SWT UI 代码会给您“无效线程访问”错误。所以大概你的应用程序在不同的线程上运行。

    您可以通过每次创建和关闭显示来运行代码:

    Display display = new Display();
    
    ... create and main loop
    
    display.close();
    

    但是这可能不适用于 Mac,因为在 macOS SWT 上需要在第一个应用线程上创建显示。

    所以基本上从 Swing 运行 SWT 代码是个坏主意。

    【讨论】:

    • 完全同意这个坏主意的评论。我是否应该预料到任何没有经验的问题(当 SWT 调用多个 Swing 应用程序时?)或者 Swing 那样好?
    • SWT 提供了SWT_AWT 类来从 SWT 运行 AWT/Swing。我不知道如果你不使用它会发生什么。
    猜你喜欢
    • 2011-08-29
    • 2014-09-07
    • 2011-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    相关资源
    最近更新 更多