1

我在下面有Ex1:

main(String args[]) {
    JFrame frame = new JFrame("Title");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JButton button = new JButton("Press Here");
    ContainerListener container = new ContainerAdapter() {
      public void componentAdded(final ContainerEvent e) {
          System.out.println("On the event thread? : " +
                  EventQueue.isDispatchThread());
      }
    };
    frame.getContentPane().addContainerListener(container);
    frame.add(button, BorderLayout.CENTER);
    frame.setSize(200, 200);
    System.out.println("I'm about to be realized: " +
      EventQueue.isDispatchThread());
    frame.setVisible(true);
  }

我的结果是:在事件线程上?: 错误 | 我即将意识到:假

其他Ex2:

public class GridBagLayoutTester
    extends JPanel implements ActionListener{   
public GridBagLayoutTester() {
    setLayout(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();

    JButton button = new JButton("Testing");
    // do something...
    button.addActionListener(this);
    add(button, gbc);
}

public void actionPerformed(ActionEvent e) {
    System.out.println("On the event thread? : " +
                  EventQueue.isDispatchThread());
}

public static void main(String[] args) {
    JFrame frame = new JFrame("GridBagLayoutDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    
    Container contentPane = frame.getContentPane();
    contentPane.setLayout(new BorderLayout());
    contentPane.add(new GridBagLayoutTester(), BorderLayout.CENTER);
    frame.setSize(800, 600);
    frame.pack();
    frame.setVisible(true);
    System.out.println("I'm about to be realized: " +
      EventQueue.isDispatchThread());
}   

}

结果是:我即将实现:假| 在事件线程上?: 真的

我的问题是为什么 Ex1-componentAdded() 在初始线程中运行,而 Ex2-actionPerformed() 在 EDT 中运行?

4

2 回答 2

3

关于 Java 中的 GUI 应用程序的一些事实:

-Java GUI应用程序中,该main()方法是短暂的,在(EDT)中调度 GUI 的构建后,它会退出Event Dispatcher Thread

-所以它有EDT's 责任处理 GUI

现在来到你的代码:

- Initial Thread 是main()线程,EDTGUI Thread

-在 EX1 中,您强制 GUI 在main()线程上运行,这是一种错误的做法,而在 EX2 中,当您使用GridBagLayoutTester扩展JPanel时,main()线程通过将 GUI 的工作委派给 EDT 来获得较早的机会.

- main()方法应该用于执行EventQueue.invokeLater()进一步处理 GUI 的方法,这将有助于 UI 响应并避免处理任何非 UI 工作。

-此外,Java 有SwingUtilities一个类,它分别在和和线程之间进行了很好的同步。UINon-UIUINon-UI

例如:正确的做法......

public class Test extends JFrame{

   public Test(){

       this.setSize(300,300);
       this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }


  public static void main(String[] args){


       EventQueue.invokeLater(new Runnable(){

              public void run(){

                   new Test().setVisible(true);

                }


           });

   }


}
于 2012-11-08T09:22:03.543 回答
2

您在 main 方法中的第一行创建了一个 JFrame 类型的新对象。这个创建启动了一个新线程(实际上它启动了多个线程)——一个等待事件队列项的新线程。例如,这可以是鼠标单击。回答您的问题:主线程 - 真正称为“main” - 正在调用 main 方法的 10 行代码。这应该在几毫秒内完成。之后主线程消失了,不再存在。但正如我之前所说,AWT/Swing 库在内部创建了一个(是的,更多)线程,基本上是一个检查用户输入的无限循环。并且从该线程调用 actionPerformed 方法。

我给你的建议:

  • 在 main 方法的第一行创建一个断点。

  • 调试你的程序。

  • 当调试器在第一行停止时(在创建 JFrame 之前)转到您的命令行并启动 jconsole

  • 转到标签线程

  • 注意线程“主”

  • 执行单行(新 JFrame)

  • 注意线程“main”和线程“AWT-*”的共存

  • 在调试器上按播放,“main”将消失,但 AWT 将持续存在

于 2012-11-08T09:32:42.080 回答