Качаем OSX: как перехватить команду-Q? - PullRequest
22 голосов
/ 14 января 2010

После того, как убедившись ("обученный"), что приложения Swing на Mac выглядят как родные , я пытаюсь сделать мой внешний вид максимально естественным. Все выглядит отлично, но когда я нажимаю command + Q или делаю это из меню, мой windowStateChanged(WindowEvent e) не запускается на моем основном JFrame (если я выхожу любым другим способом, это огонь). Как я могу ответить на настоящий Apple, бросить?

Ответы [ 6 ]

15 голосов
/ 14 января 2010

Вы можете реализовать com.apple.eawt.ApplicationListener и ответить на событие Quit. Пример можно найти в справочной библиотеке Mac OS X , OSXAdapter .

Приложение: См. Java для Mac OS X 10.6 Обновление 3 и 10.5 Обновление 8 Примечания к выпуску для получения информации об устаревании, обновленном классе com.apple.eawt.Application и расположении документации API для расширений Apple Java. Удерживая нажатой клавишу «Control» или щелкнув правой кнопкой мыши файл .jdk, выберите Show Package Contents. Вы можете просматривать классы com.apple.eawt среди источников OpenJDK.

Как показано в этом полном примере , вы можете указать желаемый 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);

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);
    }
}
6 голосов
/ 12 октября 2015

Ответ с наибольшим количеством голосов отлично, но только для того, чтобы заполнить «лучший путь»:

System.setProperty("apple.eawt.quitStrategy", "CLOSE_ALL_WINDOWS");

Это вызовет стандартное событие обратного вызова закрытия окна, которое должно очень хорошо работать для переносимого кода.

В результате обсуждения, представленного ниже, кажется, что крайне важно сделать это очень рано в приложении. Я написал это рано в статическом инициализаторе основного класса, прежде чем любой код пользовательского интерфейса был выполнен.

4 голосов
/ 14 января 2010

Это довольно хороший вопрос, и я должен признать, что у меня нет ответа . Однако пару лет назад, когда я работал над Java-приложением и столкнулся с этой проблемой, я решил ее, зарегистрировав ловушку завершения работы среды выполнения, которая выполняла бы то, что я хотел, чтобы приложение делало до выхода. Это сложное решение, но оно сработало. Вы можете взглянуть на мой код и посмотреть, поможет ли это.

3 голосов
/ 27 июня 2014

При попытке получить доступ к подклассам com.apple.eawt.Application и com.apple.eawt. * Я изначально видел нарушение «ограничения доступа».

(Примечание: я программирую на MAC, использую Eclipse, с Java 1.6 использую Swing)

Поэтому мне нужно было изменить путь сборки Java, чтобы разрешить доступ к подклассам apple, добавив правило доступа «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();

   }

});
3 голосов
/ 14 января 2010

Вы пытались настроить команду - Q в качестве ускорителя в вашем меню? Можете ли вы заставить свое приложение реагировать на это?

Я не уверен, но думаю, что это работает в Linux и, вероятно, Windows с эквивалентом Alt - F4 . Мое приложение реагирует на "убивающее" нажатие клавиши, я обрабатываю некоторый код очистки и затем выполняю программную System.exit().

Если вы «только» после изящной обработки выхода, вы можете также захотеть поймать WindowEvent WINDOW_CLOSING, где традиционно «вы уверены?» все сделано.

0 голосов
/ 15 мая 2012

Просматривая ссылку на Java для Mac OS X 10.6 Обновление 3 и 10.5 Обновление 8 Примечания к выпуску Я заметил, что есть раздел Действие по умолчанию Quit . Здесь описывается системное свойство, запрашивающее закрытие всех окон в ответ на пункт меню «Выход», что звучит как то, что нужно? Я использовал это в своем собственном приложении (используя Info.plist для установки свойства только в OS X), и похоже, что оно работает, как описано. Предполагается, что это будет работать только на последних версиях Java / OS X, но для этих платформ это выглядит аккуратным решением и не требует никаких изменений кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...