You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 10下Mac应用菜单适配求助:偏好设置与退出事件处理

解决Java 10+适配Mac应用菜单的问题(偏好设置+退出确认)

我之前在Java 10开发Mac应用时也踩过一模一样的坑!原来的com.apple.eawtAPI说移除就移除,当时查JEP 272也看懵了,后来折腾了半天终于搞懂了官方推荐的替代方案——用java.awt.Desktop和java.awt.desktop包下的新API就能搞定。我给你写个完整的示例,覆盖你要的添加偏好设置菜单、退出时弹出确认提示这两个需求。

核心API说明

原来的com.apple.eawt.Application相关功能,被拆分到了java.awt.desktop包下的一系列处理器接口里:比如处理退出的QuitHandler、处理偏好设置的PreferencesHandler,我们只需要通过Desktop类注册这些处理器,就能对接Mac的原生应用菜单。

完整实现代码

这是一个可直接运行的示例,包含菜单构建、事件监听的完整逻辑:

import javax.swing.*;
import java.awt.*;
import java.awt.desktop.PreferencesEvent;
import java.awt.desktop.PreferencesHandler;
import java.awt.desktop.QuitEvent;
import java.awt.desktop.QuitHandler;
import java.awt.desktop.QuitResponse;

public class MacMenuDemo {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            // 创建主窗口
            JFrame frame = new JFrame("Mac Java App Demo");
            frame.setSize(400, 300);
            // 一定要设为DO_NOTHING,让我们自己处理关闭事件
            frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

            // 先检查当前平台是否支持桌面API,避免跨平台报错
            if (Desktop.isDesktopSupported()) {
                Desktop desktop = Desktop.getDesktop();

                // 注册退出处理器:弹出确认提示框
                if (desktop.isSupported(Desktop.Action.APP_QUIT_HANDLER)) {
                    desktop.setQuitHandler(new QuitHandler() {
                        @Override
                        public void handleQuitRequestWith(QuitEvent quitEvent, QuitResponse quitResponse) {
                            int confirmResult = JOptionPane.showConfirmDialog(
                                    frame,
                                    "Are you sure?",
                                    "Confirm Exit",
                                    JOptionPane.YES_NO_OPTION
                            );
                            if (confirmResult == JOptionPane.YES_OPTION) {
                                quitResponse.performQuit(); // 用户确认,执行退出
                            } else {
                                quitResponse.cancelQuit(); // 用户取消,终止退出流程
                            }
                        }
                    });
                }

                // 注册偏好设置处理器
                if (desktop.isSupported(Desktop.Action.APP_PREFERENCES)) {
                    desktop.setPreferencesHandler(new PreferencesHandler() {
                        @Override
                        public void handlePreferences(PreferencesEvent preferencesEvent) {
                            // 这里替换成你的偏好设置窗口逻辑
                            JOptionPane.showMessageDialog(frame, "打开偏好设置窗口");
                        }
                    });
                }
            }

            // 构建Mac顶部的应用菜单
            MenuBar menuBar = new MenuBar();
            Menu appMenu = new Menu("我的应用");

            // 添加偏好设置菜单项,点击时触发注册的处理器
            MenuItem prefsItem = new MenuItem("偏好设置");
            prefsItem.addActionListener(e -> {
                if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.APP_PREFERENCES)) {
                    Desktop.getDesktop().getPreferencesHandler().handlePreferences(null);
                }
            });

            // 添加退出菜单项,点击时触发注册的处理器
            MenuItem quitItem = new MenuItem("退出");
            quitItem.addActionListener(e -> {
                if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.APP_QUIT_HANDLER)) {
                    Desktop.getDesktop().getQuitHandler().handleQuitRequestWith(null, new QuitResponse() {
                        @Override
                        public void performQuit() {
                            System.exit(0);
                        }

                        @Override
                        public void cancelQuit() {
                            // 取消退出时的额外逻辑可以写在这里
                        }
                    });
                }
            });

            appMenu.add(prefsItem);
            appMenu.addSeparator(); // 菜单分隔线
            appMenu.add(quitItem);
            menuBar.add(appMenu);

            // 把菜单绑定到主窗口
            frame.setMenuBar(menuBar);
            frame.setVisible(true);
        });
    }
}

关键细节提醒

  • 跨平台兼容:一定要加上Desktop.isDesktopSupported()和desktop.isSupported(...)的判断,这样代码在Windows/Linux上也能正常运行,不会抛出异常。
  • 统一退出逻辑:把窗口默认关闭操作设为JFrame.DO_NOTHING_ON_CLOSE,这样不管用户是点击窗口关闭按钮,还是用Cmd+Q快捷键,都会走我们写的确认流程。
  • 系统快捷键自动关联:注册PreferencesHandler后,Mac自带的Cmd+,快捷键会自动触发偏好设置逻辑,不需要额外配置快捷键。

内容的提问来源于stack exchange,提问作者stevem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:24:42