После будучи убежденным ( "обученным" ), что Swing-приложения на Mac выглядят родными, я пытаюсь сделать мой взгляд максимально родным. Все выглядит великолепно, но когда я нажимаю command + Q или делаю это из меню, мой windowStateChanged(WindowEvent e)
не запускает мой основной JFrame (если я выхожу иначе, он срабатывает). Как я могу ответить на настоящий Apple?
Качание на OSX: как ловушка command-Q?
Ответ 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);
Консоль, после ⌘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, но для этих платформ это похоже на аккуратное решение и не требует каких-либо изменений кода.