2017-04-11 3 views
2

Ich habe eine Java-Swing-Anwendung, die eine ProcessWindowEvent-Methode hat. unten ist das SnippetProcessWindowEvent in Mac

@Override 
    protected void processWindowEvent(WindowEvent e) { 
    if (e.getID() == WindowEvent.WINDOW_CLOSING) { 
     //exit application with proper error message 
    } 
    } 

Nun, wenn meine Swing-Anwendung in Windows gestartet wird.

  1. schließen Sie mit dem Kreuz in Schwung UI. ==> korrekte Fehlermeldung angezeigt
  2. die Anwendung von Task-Leiste schließen, ==> korrekte Fehlermeldung angezeigt

aber jetzt, wenn der gleiche Schritt in dem Mac getan.

  1. schließen mit dem Kreuz in Schwung UI. ==> richtige Fehlermeldung wird angezeigt
  2. Schließen Sie die Anwendung von der Taskleiste ==> kommt nicht nach oben Methode. Also keine richtige Nachricht.

Ich wollte wissen, was die Methode Standard ist, die in Mac aufgerufen wird, wenn Java-Swing-App von Taskleiste (das Dock) geschlossen ist

Antwort

2

Willkommen in der wunderbaren Welt der „Apple-tut alles anders“

Im Grunde, was passiert ist, wenn Sie auf „Beenden“, um das Programm, Apple-Anruf ist System.exit(0), im Grunde die gleiche Sache, die Sie verwendet würde auftreten, wenn CMD + Q

Jetzt Apple eine API, die Funktionalität bereitstellt bereitstellt, die Sie „konfigurieren“, um Ihre App mit MacOS verwenden können, um und einige Funktionen ausführen, die einzigartig ist Apple, das Problem ist, es ist ein kompletter Schmerz im ... Code, um nützliche Informationen zu finden und zu verwenden.

Was Sie suchen, ist com.apple.eawt.ApplictionsetQuitStrategy. Dies ruft standardmäßig System.exit(0) auf, aber Sie können stattdessen "Alle Fenster schließen" ändern.

In diesem Fall würde es Ihnen zu stoppen lassen die WindowEvent und tun, was immer es ist, Sie

import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame frame = new JFrame(); 
       frame.add(new TestPane()); 
       frame.addWindowListener(new WindowAdapter() { 
        @Override 
        public void windowClosing(WindowEvent e) { 
         System.out.println("Closing"); 
         System.exit(0); 
        } 
       }); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 

       try { 
        Class quitStrategies = Class.forName("com.apple.eawt.QuitStrategy"); 
        Object quitStrategy = null; 
        for (Object o : quitStrategies.getEnumConstants()) { 
         if ("CLOSE_ALL_WINDOWS".equals(o.toString())) { 
          quitStrategy = o; 
         } 
        } 
        if (quitStrategy != null) { 
         Class appClass = Class.forName("com.apple.eawt.Application"); 
         Class params[] = new Class[]{}; 

         Method getApplication = appClass.getMethod("getApplication", params); 
         Object application = getApplication.invoke(appClass); 
         Method setQuitStrategy = application.getClass().getMethod("setQuitStrategy", quitStrategies); 
         setQuitStrategy.invoke(application, quitStrategy); 
        } 

       } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | ClassNotFoundException ex) { 
        ex.printStackTrace(); 
       } 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 
    } 
} 

Meine allgemeine Beratung ist, bauen ein schönes „Mac“ Dienstprogramme Klasse tun wollen, die die Funktionalität kapselt du willst damit spielen und das nennen.

Auch Vorsicht, diese Funktionalität kann in zukünftigen Versionen plötzlich verschwinden.

Es sollte beachtet werden, dass wenn Sie beabsichtigen, eine "eine für alle" -Anwendung zu haben, müssen Sie Reflexion verwenden, da die erforderliche API nicht in der Standard-API verfügbar ist, aber wenn Sie einen "Apple "nur veröffentlichen, sollten Sie einen Blick auf this für weitere Informationen darüber, wie Sie den Code auf MacOS kompilieren, weil mit ...

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

verdammt viel einfacher ist, zu schreiben und verstehen

+0

Ich hatte eine System.exit (0) für Erfolgsszenario. und für Mac, wenn es System.exit (0) zurückgibt, wenn es geschlossen wurde, wurde es als Erfolg angezeigt. Danke für die Information. Ich werde den Erfolgscode auf etwas anderes als 0 ändern –

1

Zum Fenster schließen Ereignis Sie WindowListener hinzufügen müssen fangen und Methode überschreiben windowClosing. Verwenden Sie diesen Code:

JFrame frame = new JFrame(...); 
    frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); 

    frame.addWindowListener(new WindowAdapter() 
    { 
     public void windowClosing(WindowEvent e) 
     { 
      JFrame frame = (JFrame)e.getSource(); 
    .................... 
} 
} 
+0

Wenn 'processWindowEvent' nicht aufgerufen wurde, wird die' WindowListener' nicht – MadProgrammer

+0

(1+) dies vielleicht aufgerufen wird, nicht die Lösung Problem, aber ja, Sie sollten einen 'WindowListener' verwenden, um das Schließen eines Fensters zu behandeln, anstatt die processWindowEvent (...) Methode zu überschreiben. – camickr