Oscilla su OSX: Comando Trap-Q?

Dopo essere stato convinto (“istruito”) che le app di Swing su Mac sembrano native , sto cercando di rendere il mio più nativo ansible. Tutto sembra windowStateChanged(WindowEvent e) , ma quando windowStateChanged(WindowEvent e) comando + Q o lo faccio dal menu, la mia windowStateChanged(WindowEvent e) non sta sparando sul mio JFrame principale (se windowStateChanged(WindowEvent e) in un altro modo, fa fuoco). Come posso rispondere alla vera uscita di Apple?

La risposta più votata è eccellente, ma solo per riempire il “modo migliore”:

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

Ciò attiverà l’evento di callback di chiusura della finestra standard che dovrebbe funzionare molto bene per il codice portatile.

Come risultato della discussione qui di seguito sembra che sia fondamentale farlo all’inizio dell’app. L’ho scritto all’inizio dell’inizializzatore statico della class principale prima dell’esecuzione di qualsiasi codice UI.

È ansible implementare com.apple.eawt.ApplicationListener e rispondere all’evento Quit . Un esempio può essere trovato nell’esempio della libreria di riferimento di Mac OS X , OSXAdapter .

Addendum: vedere Java per Mac OS X 10.6 Update 3 e 10.5 Note di rilascio dell’aggiornamento 8 per informazioni sulla deprecazione, la class com.apple.eawt.Application riprogettata e la posizione della documentazione dell’API per le estensioni di Apple Java. Fare clic .jdk il .jdk Ctrl o fare clic con il pulsante destro del mouse sul file .jdk per visualizzare i Show Package Contents . Puoi consultare le classi di com.apple.eawt tra i sorgenti OpenJDK.

Come mostrato in questo esempio completo, è ansible specificare la QuitStrategy desiderata; un WindowListener risponderà a ⌘Q :

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

Come indicato qui , è ansible impostare la proprietà dalla riga di comando

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

o all’inizio del programma, prima di pubblicare qualsiasi evento della GUI:

 System.setProperty("apple.eawt.quitStrategy", "CLOSE_ALL_WINDOWS"); EventQueue.invokeLater(new QuitStrategyTest()::display); 

Immagine

Console, dopo ⌘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 

Codice:

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

Questa è una domanda abbastanza buona, e devo ammettere che non ho la risposta. Tuttavia, un paio di anni fa, quando stavo lavorando su un’app Java e ho affrontato questo problema, l’ho risolto registrando un hook di shutdown con il runtime che avrebbe fatto ciò che volevo che l’app facesse prima di uscire. È una soluzione pesante ma ha funzionato. Puoi dare un’occhiata al mio codice e vedere se aiuta.

Inizialmente vedevo una violazione di “restrizione dell’accesso” quando provavo ad accedere alle sottoclassi com.apple.eawt.Application e com.apple.eawt. *.

(Nota: sto programmando su un MAC, usando Eclipse, con Java 1.6 usando Swing)

Quindi ho dovuto modificare il mio percorso di costruzione java per consentire l’accesso alle sottoclassi di apple aggiungendo la regola di accesso “com / apple / eawt / **”. Dopo che questo codice qui sotto è stato in grado di compilare e lavorare per me:

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

Hai provato a impostare il comando : Q come acceleratore nel tuo menu? Puoi fare in modo che la tua app risponda?

Non sono positivo, ma penso che funzioni su Linux e probabilmente su Windows con l’equivalente AltF4 . La mia app risponde alla sequenza di “uccisione”, elaboro un po ‘di codice di pulizia e poi faccio un System.exit() programmatico.

Se sei “solo” dopo una gestione di uscita aggraziata, potresti anche voler catturare WindowEvent WINDOW_CLOSING , dove tradizionalmente “sei sicuro?” cose fatte.

Osservando il collegamento a Java per Mac OS X 10.6 Update 3 e 10.5 Update 8 Note di rilascio ho notato che esiste una sezione sull’azione di uscita predefinita . Questo descrive una proprietà di sistema per richiedere che tutte le windows siano chiuse in risposta alla voce di menu “Esci”, che suona esattamente come è necessario? Ho usato questo nella mia applicazione (usando Info.plist per impostare la proprietà solo su OS X), e sembra funzionare come descritto. Questo presumibilmente funzionerebbe solo su versioni recenti di Java / OS X, ma per quelle piattaforms sembra una soluzione accurata e non richiede alcuna modifica al codice.