在被说服("学校")后,Swing应用程序在Mac上看起来很本地化之后,我正在尝试使我的应用程序尽可能本地化。一切看起来都很好,但是当我按下command+Q或从菜单中退出时,我的windowStateChanged(WindowEvent e)
不会在我的主JFrame上触发(如果我以其他任何方式退出,则会触发)。如何响应真正的苹果退出?
在被说服("学校")后,Swing应用程序在Mac上看起来很本地化之后,我正在尝试使我的应用程序尽可能本地化。一切看起来都很好,但是当我按下command+Q或从菜单中退出时,我的windowStateChanged(WindowEvent e)
不会在我的主JFrame上触发(如果我以其他任何方式退出,则会触发)。如何响应真正的苹果退出?
com.apple.eawt.ApplicationListener
并响应Quit
事件。在Mac OS X Reference Library示例中,可以找到一个例子,OSXAdapter。com.apple.eawt.Application
类以及苹果Java扩展的API文档位置。控制单击或右键单击.jdk
文件以Show Package Contents
。您可以在OpenJDK源代码中浏览com.apple.eawt
类。QuitStrategy
;WindowListener
将响应⌘Q:Application.getApplication().setQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS);
正如这里所指出的,你可以从命令行设置该属性。
java -Dapple.eawt.quitStrategy=CLOSE_ALL_WINDOWS -cp build/classes gui.QuitStrategyTest
或者在程序早期,在发布任何GUI事件之前:
System.setProperty("apple.eawt.quitStrategy", "CLOSE_ALL_WINDOWS");
EventQueue.invokeLater(new QuitStrategyTest()::display);
按下⌘Q后的控制台:
java.vendor: Oracle Corporation
java.version: 1.8.0_60
os.name: Mac OS X
os.version: 10.11
apple.eawt.quitStrategy: CLOSE_ALL_WINDOWS
java.awt.event.WindowEvent[WINDOW_CLOSING,opposite=null,oldState=0,newState=0] on frame0
代码:
package gui;
import java.awt.EventQueue;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JTextArea;
/**
* @see https://dev59.com/yms05IYBdhLWcg3wFOC8#7457102
*/
public class QuitStrategyTest {
private void display() {
JFrame f = new JFrame("QuitStrategyTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.out.println(e);
}
});
f.add(new JTextArea(getInfo()));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private String getInfo() {
String[] props = {
"java.vendor",
"java.version",
"os.name",
"os.version",
"apple.eawt.quitStrategy"
};
StringBuilder sb = new StringBuilder();
for (String prop : props) {
sb.append(prop);
sb.append(": ");
sb.append(System.getProperty(prop));
sb.append(System.getProperty("line.separator"));
}
System.out.print(sb);
return sb.toString();
}
public static void main(String[] args) {
System.setProperty("apple.eawt.quitStrategy", "CLOSE_ALL_WINDOWS");
EventQueue.invokeLater(new QuitStrategyTest()::display);
}
}
该问题最受欢迎的回答已经很好了,但是为了填补“最佳方法”的空白:
System.setProperty("apple.eawt.quitStrategy", "CLOSE_ALL_WINDOWS");
Application.getApplication().setQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS);
一样的吗? - Dan Rosenstarkcommand-Q
方面并不相同;我已经更新了此处引用的示例,以展示一种可移植的方法;删除对enableOSXQuitStrategy()
的调用以查看效果。 - trashgodcommand-Q
或应用程序菜单发送;我很高兴发现我错了! :-) - trashgod在试图访问com.apple.eawt.Application和com.apple.eawt.*子类时,我最初遇到了“访问限制”违规。
(注意:我正在使用Eclipse,在MAC上编程,使用Java 1.6和Swing)
因此,我需要修改我的Java构建路径,通过添加“com/apple/eawt/**”访问规则来允许访问苹果子类。之后,下面的代码能够成功编译并运行:
//NOTE: This code only works for MAC OS. If you run this on Windows
//the application never starts (so you literally need to remove this block of code)
import com.apple.eawt.*;
import com.apple.eawt.QuitHandler;
Application a = Application.getApplication();
a.setQuitHandler(new QuitHandler() {
@Override
public void handleQuitRequestWith(com.apple.eawt.AppEvent.QuitEvent qe, com.apple.eawt.QuitResponse qr) {
// TODO Auto-generated method stub
int res = JOptionPane.showConfirmDialog(frame, "Are you sure you want to exit the program?", "Quit ?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (res == JOptionPane.YES_OPTION)
qr.performQuit();
else
qr.cancelQuit();
}
});
这是一个非常好的问题,我必须承认我没有确切的答案。不过,几年前当我在开发一款Java应用程序时遇到了这个问题,我通过向运行时注册一个关机挂钩来解决它,以执行我想要应用程序在退出之前完成的操作。这是一个很笨重的解决方案,但它起作用了。你可以查看我的代码,看看是否有所帮助。
System.exit()
。如果您只是想要优雅地退出处理,您也可以捕获WindowEvent
WINDOW_CLOSING
,在那里传统上会执行“您确定吗?”的操作。看了一下Java for Mac OS X 10.6 Update 3 and 10.5 Update 8 Release Notes的链接,我注意到有一个关于默认退出操作的部分。这描述了一个系统属性,请求在响应“退出”菜单项时关闭所有窗口,听起来正是所需的?我已经在我的应用程序中使用了这个(仅在OS X上使用Info.plist设置属性),它似乎按照描述的方式工作。这可能只适用于最近的Java/OS X版本,但对于这些平台来说,似乎是一个不错的解决方案,而且不需要任何代码更改。