4

我刚刚开始掌握java中的GUI编程。这是一个琐碎的程序(来自 O'Reilly 的“Head First Java”),表面上看起来很容易理解,但它有一个方面我不理解。

import javax.swing.*;

public class Test {
    public static void main(String[] args) {

    JFrame frame=new JFrame();
    JButton button = new JButton("click me");

    frame.getContentPane().add(button); 
        frame.setSize(300,300);
    frame.setVisible(true);
    }
}

这个简单的程序在编译并运行后会打开一个带有按钮的窗口。

我不明白执行流程发生了什么。当我运行这个程序时,Test类的静态main方法运行,里面的所有命令main()都被执行了——那么为什么窗口出现后进程没有终止呢?为什么我仍然坐在看起来像无限循环的地方?什么是循环?

如果我添加该行

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

然后我发现结果更加难以理解。现在,当然,一旦我关闭了窗口,程序就会终止。但我又不明白为什么。框架将在堆栈上,但我看不到程序流在哪里,并且堆栈上的某些东西的存在不足以使程序保持活力,肯定吗?我错过了一些基本的东西,据我所知,我正在阅读的书中没有涵盖这些内容。我对此感到有些惊讶——到目前为止,“Head first Java”在指出细微之处和解释真正发生的事情方面做得非常好,但似乎没有解决这一点(至少我没有发现)。

4

2 回答 2

4

为什么窗口出现后进程不终止?

因为 Java 虚拟机只有在所有非守护线程都完成后才会退出。虽然不明显,但实际上您的程序中有两个线程:主线程和事件分派线程,它执行与 Swing GUI 组件相关的所有工作。只要任何 GUI 组件可见,事件调度线程就会继续运行。

实际上,该程序虽然可以工作,但它是错误的,因为您正在从主线程创建和访问 Swing 组件。您应该在事件分派线程中完成所有 GUI 工作。也就是说,它应该是这样的:

public static void main(String[] args) {

  EventQueue.invokeLater(new Runnable() {
    JFrame frame=new JFrame();
    JButton button = new JButton("click me");

    frame.getContentPane().add(button); 
    frame.setSize(300,300);
    frame.setVisible(true);
  });
}
于 2012-02-05T13:50:04.767 回答
1

当最后一个非恶魔线程死亡时,Java 进程终止。通常只有一个,main线程。当您显示 Swing 组件时,会启动用于事件分派和 GUI 击落的附加非恶魔线程。当最后一个顶级组件被释放时,那些终止。在您的示例中,main线程在离开该main方法后死亡。您可以使用调试器或jvisualvmJDK 工具查看线程。

GUI 流程的其余部分是事件驱动的。例如,当您单击框架的关闭按钮时,会生成一个事件并将其发送到事件调度线程中的适当侦听器。

设置JFrame.EXIT_ON_CLOSE为默认关闭操作就像向框架添加默认事件侦听器。一个相当苛刻的,它只是关闭 JVM 而不考虑应用程序的其余状态。

于 2012-02-05T13:56:22.923 回答