Java 来自SWT和Swing的混合框架(JFrame)

Java 来自SWT和Swing的混合框架(JFrame),java,swing,user-interface,jframe,swt,Java,Swing,User Interface,Jframe,Swt,我得到了大量基于JFrame的小窗口,这些窗口最初作为单独的微应用程序工作。因此,每种方法都有自己的主方法,其中包含添加到EventQueue的Runnable 我应该将它与SWT主框架应用程序合并,以便用户可以调用任何单独的基于Swing的微应用程序。因此,最终的方案是使用一个顶部框架SWT来调用各个JFrame子应用程序。我知道这不是正确构建GUI应用程序的方式,但这是我被赋予的任务 当SWT是一个主项并且它调用多个基于Swing的JFrames时,一切正常(您可以尝试运行SWTApp.ma

我得到了大量基于JFrame的小窗口,这些窗口最初作为单独的微应用程序工作。因此,每种方法都有自己的主方法,其中包含添加到EventQueue的Runnable

我应该将它与SWT主框架应用程序合并,以便用户可以调用任何单独的基于Swing的微应用程序。因此,最终的方案是使用一个顶部框架SWT来调用各个JFrame子应用程序。我知道这不是正确构建GUI应用程序的方式,但这是我被赋予的任务

  • 当SWT是一个主项并且它调用多个基于Swing的JFrames时,一切正常(您可以尝试运行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)位于 createContents(SWTApp.java:46)位于 com.stackoverflow.SWTApp.open(SWTApp.java:32)位于 com.stackoverflow.SWTApp.main(SWTApp.java:21)位于 SwingApp$2$1.run(SwingApp.java:48)在 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(此处简化):


    当尚未创建任何显示时调用
    Display.getDefault()
    ,将当前线程建立为SWT用户界面线程。此线程保持不变,直到显示屏关闭。在任何其他线程上执行SWT UI代码将导致“线程访问无效”错误。因此,您的应用程序可能运行在不同的线程上

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

    Display display = new Display();
    
    ... create and main loop
    
    display.close();
    
    然而,这在Mac上可能不起作用,因为macOS SWT要求在第一个应用程序线程上创建显示


    因此,基本上从Swing运行SWT代码是一个坏主意。

    在尚未创建任何显示时调用
    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\u AWT
    类来从SWT运行AWT/Swing。我不知道如果你不使用它会发生什么。完全同意这个坏主意的评论。我是否应该以另一种方式(当SWT调用多个Swing应用程序时?)期待任何未经体验的问题,或者Swing是这样好吗?SWT提供了
    SWT\u AWT
    类来从SWT运行AWT/Swing。我不知道如果你不使用它会发生什么。