在being convinced ("schooled") that Swing apps on Mac do look native之后,我试图让我看起来尽可能本地。一切看起来都很棒,但当我点击命令 + Q 或从菜单中执行此操作时,我的windowStateChanged(WindowEvent e)
未在我的主JFrame上触发(如果我退出任何其他方式,它确实火了)。我如何回应真正的苹果退出?
答案 0 :(得分:15)
您可以实施com.apple.eawt.ApplicationListener
并回复Quit
事件。可以在 Mac OS X参考库示例OSXAdapter中找到示例。
附录:有关弃用的信息,重新设计的com.apple.eawt.Application
类以及Apple Java扩展的API文档的位置,请参阅Java for Mac OS X 10.6 Update 3 and 10.5 Update 8 Release Notes。按住Control键并单击或右键单击.jdk
文件到Show Package Contents
。您可以在OpenJDK源中浏览com.apple.eawt
的类。
如完整example所示,您可以指定所需的内容
QuitStrategy
; WindowListener
将响应⌘Q:
Application.getApplication().setQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS);
如上所述here,您可以从命令行
设置属性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://stackoverflow.com/a/7457102/230513
*/
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);
}
}
答案 1 :(得分:6)
The top voted answer非常出色,但只是填写“最佳方式”:
System.setProperty("apple.eawt.quitStrategy", "CLOSE_ALL_WINDOWS");
这将触发标准窗口关闭回调事件,该事件对于可移植代码应该非常好用。
作为下面讨论的结果,似乎在应用程序中尽早完成此操作至关重要。在执行任何UI代码之前,我在主类的静态初始化程序中尽早编写了这个。
答案 2 :(得分:4)
这是一个非常好的问题,我必须承认我没有 的答案。然而,几年前,当我在Java应用程序上工作并遇到这个问题时,我通过在运行时注册一个关闭钩子解决了这个问题,这个钩子会在退出之前做我希望应用程序做的事情。这是一个严厉的解决方案,但它的工作原理。您可以take a look at my code查看是否有帮助。
答案 3 :(得分:3)
您是否尝试在菜单中设置命令 - Q 作为加速器?你可以让你的应用回应吗?
我不是肯定的,但我认为这适用于Linux,可能还有Windows,等效的 Alt - F4 。我的应用程序响应“查杀”按键,我处理一些清理代码,然后我执行程序化System.exit()
。
如果你在优雅的退出处理之后“只是”,你可能还想抓住WindowEvent
WINDOW_CLOSING
,传统上“你确定吗?”事情已经完成。
答案 4 :(得分:3)
我原本看到了一个访问限制'尝试访问com.apple.eawt.Application和com.apple.eawt。*子类时发生违规。
(注意:我在MAC上编程,使用Eclipse,使用Swing编写Java 1.6)
所以我需要修改我的java构建路径以允许通过添加" com / apple / eawt / **"来访问apple子类。访问规则。之后,下面的代码能够为我编译和工作:
//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();
}
});
答案 5 :(得分:0)
查看Java for Mac OS X 10.6 Update 3 and 10.5 Update 8 Release Notes的链接,我注意到默认退出操作上有一节。这描述了一个系统属性,它要求关闭所有窗口以响应“退出”菜单项,这听起来就像需要的那样?我在我自己的应用程序中使用它(使用Info.plist仅在OS X上设置属性),它似乎按照描述工作。这可能只适用于最近的Java / OS X版本,但对于那些平台来说似乎是一个简洁的解决方案,并且不需要任何代码更改。