我正在尝试用 Java 编写一个还运行 Google AppEngine Dev-Server 的 Swing 应用程序(请参阅开发使用 AppEngine 数据库的 Java 应用程序)并且遇到了 Swing Eventloop 的一个奇怪问题。
我有以下两个课程:
调试窗口,最终将接收日志消息等:
public class DebugWindow {
private static JFrame debugWindow = null;
private static JTextArea debugContent = null;
public static void show() {
debugWindow = new JFrame("Debug");
debugWindow.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
debugContent = new JTextArea("Debug messages go here!");
debugWindow.add(debugContent, BorderLayout.CENTER);
debugWindow.pack();
debugWindow.setVisible(true);
}
}
加载 Google AppEngine Dev-Server 的辅助类:
// other imports
import com.google.appengine.tools.development.DevAppServerMain;
public class DevServer {
public static void launch(final String[] args, boolean waitFor) {
Logger logger = Logger.getLogger("");
logger.info("Launching AppEngine server...");
Thread server = new Thread() {
@Override
public void run() {
try {
DevAppServerMain.main(args); // run DevAppServer
} catch (Exception e) { e.printStackTrace(); }
}
};
server.setDaemon(true); // shut down server when rest of app completes
server.start(); // run server in separate thread
if (!waitFor) return; // done if we don't want to wait for server
URLConnection cxn;
try {
cxn = new URL("http://localhost:8888").openConnection();
} catch (IOException e) { return; } // should never happen
boolean running = false;
while (!running) {
try {
cxn.connect(); // try to connect to server
running = true;
} catch (Exception e) {}
}
logger.info("Server running.");
}
}
我的main(...)
方法如下所示:
public static void main(final String[] args) throws Exception {
DevServer.launch(args, true); // launch and wait for AppEngine dev server
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
DebugWindow.show(); // create and show debug window
}
});
}
有了这个,我得到了一些关于 Swing Eventloop 的非常奇怪的行为:
- 首先,Swing 应该工作的方式:如果我注释掉 中的行
DevServer.launch(...)
,main(...)
应用程序就会启动,显示调试窗口,继续运行,当我关闭调试窗口时,它会关闭。 - 如果我
DevServer.launch(...)
重新添加,它会按预期启动服务器,然后立即退出(它可能还短暂地显示了调试窗口,但它太快看到了)。 - 如果我
DevServer.launch(...)
在 之后移动行SwingUtilities.invokeLater(...)
,它会显示调试窗口,然后启动服务器,当服务器启动时,它会立即退出。 - 现在它变得非常奇怪:如果我将行更改为
DevServer.launch(args, false)
,即我不等待服务器实际启动,而只是让我的main(...)
方法立即完成,调试窗口显示,服务器正确加载,应用程序继续运行,但是如果我关闭调试窗口不会退出?! - 如果我随后也更改
JFrame.DISPOSE_ON_CLOSE
为JFrame.EXIT_ON_CLOSE
,则显示调试窗口,服务器加载正确,应用程序继续运行,如果我关闭调试窗口,它会正确退出。
知道 Swing 事件循环在这里发生了什么吗?我被难住了......是否有什么事情会导致 Swing 事件循环提前终止(场景 2 和 3)?多线程应用程序是否会阻止 Swing 检测到最后释放的窗口(场景 4)?