在OSX上摇摆:如何捕获命令-Q?

时间:2010-01-13 23:47:13

标签: java swing macos

being convinced ("schooled") that Swing apps on Mac do look native之后,我试图让我看起来尽可能本地。一切看起来都很棒,但当我点击命令 + Q 或从菜单中执行此操作时,我的windowStateChanged(WindowEvent e)未在我的主JFrame上触发(如果我退出任何其他方式,它确实火了)。我如何回应真正的苹果退出?

6 个答案:

答案 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);

image

控制台,在⌘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版本,但对于那些平台来说似乎是一个简洁的解决方案,并且不需要任何代码更改。