有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java swing如何在另一个线程中打开框架

我的自定义JFrame实现了runnable接口,因此它包含run方法,在我的main方法中,我尝试打开我的框架:

public static void main(String[] args) {

      new Thread() {
          @Override
          public void run() {
              Cadre cadre = new Cadre();
          }
      }.start();
}

不幸的是,这并没有使帧出现,它似乎忽略了帧的run方法

这是我的课:

public class Cadre extends JFrame implements Runnable {
    private PanneauHaut panneauHaut;
    private PanneauBas panneauBas;

    @Override
    public void run() {
        System.out.println("Thread started"); 
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setExtendedState(JFrame.MAXIMIZED_BOTH);
        this.panneauHaut = new PanneauHaut();
        this.panneauBas = new PanneauBas();
        JPanel mainPanel = new JPanel();
        JTextField kooltxt = new JTextField("hehehe");
        mainPanel.setLayout(new BorderLayout());
        mainPanel.add(panneauHaut, BorderLayout.NORTH);
        mainPanel.add(panneauBas.getPanel(), BorderLayout.SOUTH);
        this.setContentPane(mainPanel);
        this.setVisible(true);
    }
}

有什么不对劲吗


共 (2) 个答案

  1. # 1 楼答案

    你不能也不应该。Swing是单线程的,不安全。查看Concurrency in Swing了解更多详细信息

    “主要”问题是,您正在Threadrun方法中创建一个新实例Cadre,但没有任何东西调用Cadresrun方法

    new Thread() {
        @Override
        public void run() {
            Cadre cadre = new Cadre();
        }
    }.start();
    

    哪里叫Cadre#run

    “更好”的解决方案是做一些更像EventQueue.invokeLater(new Cadre())的事情,它将在事件调度线程的上下文中安全地执行Cadrerun方法

    Nothing happens with invokeLater

    对我来说效果很好——任何额外的问题都可能是你没有提供的代码中的其他地方,或者你需要进行清理和构建,以清除任何“过时”的二进制文件

    import java.awt.BorderLayout;
    import java.awt.EventQueue;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import javax.swing.WindowConstants;
    
    public class Test {
    
      public static void main(String[] args) {
        EventQueue.invokeLater(new Cadre());
      }
    
      public static class Cadre extends JFrame implements Runnable {
    
    //  private PanneauHaut panneauHaut;
    //  private PanneauBas panneauBas;
    
        @Override
        public void run() {
          System.out.println("Thread started");
          this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    //    setExtendedState(JFrame.MAXIMIZED_BOTH);
    //    this.panneauHaut = new PanneauHaut();
    //    this.panneauBas = new PanneauBas();
          JPanel mainPanel = new JPanel();
          JTextField kooltxt = new JTextField("hehehe");
          mainPanel.setLayout(new BorderLayout());
          mainPanel.add(kooltxt);
    //    mainPanel.add(panneauHaut, BorderLayout.NORTH);
    //    mainPanel.add(panneauBas.getPanel(), BorderLayout.SOUTH);
          this.setContentPane(mainPanel);
          pack();
          setLocationRelativeTo(null);
          this.setVisible(true);
        }
      }
    
    }
    
  2. # 2 楼答案

    it seems to ignore the frame's run method

    当然了。您已经实例化了Thread的一个匿名子类,其run()方法只通过其默认构造函数实例化Cadre。没有任何东西会导致新的Cadrerun()方法运行

    您可以通过接受Runnable的构造函数实例化股票Thread()

    new Thread(new Cadre()).start();
    

    。。。但这似乎毫无意义

    请特别注意,Swing本身在另一个线程“事件调度线程”中完成所有工作,Swing和标准Swing组件不是线程安全的

    那就更好了

    SwingUtilities.invokeAndWait(new Cadre());
    

    (或invokeLater(new Cadre())),但这将导致Cadrerun()方法在事件调度线程上运行,而不是在您选择的其他随机线程上运行。事实上,这可能是您应该做的事情,因为所讨论的方法构造并显示了一个Swing GUI,但这并不是您似乎认为您想要做的事情