Качание на OSX: как ловушка command-Q?

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

Ответ 1

Самый верный ответ отличный, но просто для того, чтобы заполнить "лучший способ":

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

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

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

Ответ 2

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

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

Как показано в этом полном , вы можете указать желаемый QuitStrategy; a WindowListener ответит на ⌘Q:

Application.getApplication().setQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS);

Как указано здесь, вы можете установить свойство из командной строки

java -Dapple.eawt.quitStrategy=CLOSE_ALL_WINDOWS -cp build/classes gui.QuitStrategyTest

или в начале программы перед публикацией каких-либо графических событий:

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);
    }
}

Ответ 3

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

Ответ 4

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

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

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

Ответ 5

Первоначально я видел нарушение "ограничения доступа" при попытке доступа к подклассам 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();

   }

});

Ответ 6

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