Comment fermer une application Java Swing à partir du code

Quelle est la bonne façon de terminer une application Swing à partir du code et quels sont les pièges?

J’avais essayé de fermer mon application automatiquement après une timer. Mais le fait d’appeler dispose() sur le JFrame n’a pas fait l’affaire – la fenêtre a disparu mais l’application ne s’est pas terminée. Cependant, lorsque vous fermez la fenêtre avec le bouton Fermer, l’application se termine. Que devrais-je faire?

Votre action de fermeture par défaut JFrame peut être définie sur ” DISPOSE_ON_CLOSE ” au lieu de EXIT_ON_CLOSE (pourquoi les gens continuent à utiliser EXIT_ON_CLOSE est au-delà de moi).

Si vous avez des fenêtres ou des threads non démonisés, votre application ne se terminera pas. Cela devrait être considéré comme une erreur (et le résoudre avec System.exit est une très mauvaise idée).

Les causes les plus courantes sont java.util.Timer et un fil de discussion personnalisé que vous avez créé. Les deux doivent être définis sur daemon ou doivent être explicitement supprimés.

Si vous souhaitez vérifier tous les frameworks actifs, vous pouvez utiliser Frame.getFrames() . Si tous les fenêtres / frameworks sont supprimés, utilisez un débogueur pour rechercher les threads autres que les démons en cours d’exécution.

Je suppose qu’un EXIT_ON_CLOSE

 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

avant System.exit(0) est préférable car vous pouvez écrire un Listener Window pour effectuer certaines opérations de nettoyage avant de quitter l’application.

Cet écouteur de fenêtre vous permet de définir:

 public void windowClosing(WindowEvent e) { displayMessage("WindowListener method called: windowClosing."); //A pause so user can see the message before //the window actually closes. ActionListener task = new ActionListener() { boolean alreadyDisposed = false; public void actionPerformed(ActionEvent e) { if (frame.isDisplayable()) { alreadyDisposed = true; frame.dispose(); } } }; Timer timer = new Timer(500, task); //fire every half second timer.setInitialDelay(2000); //first delay 2 seconds timer.setRepeats(false); timer.start(); } public void windowClosed(WindowEvent e) { //This will only be seen on standard output. displayMessage("WindowListener method called: windowClosed."); } 

Essayer:

 System.exit(0); 

Brut, mais efficace.

Peut-être le moyen sûr est quelque chose comme:

  private JButton btnExit; ... btnExit = new JButton("Quit"); btnExit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ Container frame = btnExit.getParent(); do frame = frame.getParent(); while (!(frame instanceof JFrame)); ((JFrame) frame).dispose(); } }); 

Le programme suivant inclut le code qui mettra fin à un programme sans threads externes sans appeler explicitement System.exit (). Pour appliquer cet exemple aux applications utilisant des threads / listeners / timers / etc, il suffit d’insérer le code de nettoyage demandant (et, le cas échéant, en attente) leur terminaison avant que WindowEvent ne soit lancé manuellement dans actionPerformed ().

Pour ceux qui souhaitent copier / coller du code capable de fonctionner exactement comme indiqué, une méthode principale légèrement laide mais sans importance est incluse à la fin.

 public class CloseExample extends JFrame implements ActionListener { private JButton turnOffButton; private void addStuff() { setDefaultCloseOperation(DISPOSE_ON_CLOSE); turnOffButton = new JButton("Exit"); turnOffButton.addActionListener(this); this.add(turnOffButton); } public void actionPerformed(ActionEvent quitEvent) { /* Iterate through and close all timers, threads, etc here */ this.processWindowEvent( new WindowEvent( this, WindowEvent.WINDOW_CLOSING)); } public CloseExample() { super("Close Me!"); addStuff(); } public static void main(Ssortingng[] args) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { CloseExample cTW = new CloseExample(); cTW.setSize(200, 100); cTW.setLocation(300,300); cTW.setVisible(true); } }); } } 

Si je vous comprends bien, vous souhaitez fermer l’application même si l’utilisateur n’a pas cliqué sur le bouton Fermer. Vous devrez peut-être enregistrer WindowEvents avec addWindowListener () ou enableEvents (), selon ce qui convient le mieux à vos besoins.

Vous pouvez ensuite appeler l’événement avec un appel à processWindowEvent (). Voici un exemple de code qui créera un JFrame, attendez 5 secondes et fermez JFrame sans interaction de l’utilisateur.

 import javax.swing.*; import java.awt.*; import java.awt.event.*; public class ClosingFrame extends JFrame implements WindowListener{ public ClosingFrame(){ super("A Frame"); setSize(400, 400); //in case the user closes the window setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); //enables Window Events on this Component this.addWindowListener(this); //start a timer Thread t = new Timer(); t.start(); } public void windowOpened(WindowEvent e){} public void windowClosing(WindowEvent e){} //the event that we are interestd in public void windowClosed(WindowEvent e){ System.exit(0); } public void windowIconified(WindowEvent e){} public void windowDeiconified(WindowEvent e){} public void windowActivated(WindowEvent e){} public void windowDeactivated(WindowEvent e){} //a simple timer class Timer extends Thread{ int time = 10; public void run(){ while(time-- > 0){ System.out.println("Still Waiting:" + time); try{ sleep(500); }catch(InterruptedException e){} } System.out.println("About to close"); //close the frame ClosingFrame.this.processWindowEvent( new WindowEvent( ClosingFrame.this, WindowEvent.WINDOW_CLOSED)); } } //instantiate the Frame public static void main(Ssortingng args[]){ new ClosingFrame(); } } 

Comme vous pouvez le constater, la méthode processWindowEvent () provoque le déclenchement de l’événement WindowClosed où vous avez la possibilité de faire du code de nettoyage si vous en avez besoin avant de fermer l’application.

Consultez la documentation Oracle .

A partir de JDK 1.4, une application se termine si:

  • Il n’y a pas de composants AWT ou Swing affichables.
  • Il n’y a pas d’événements natifs dans la queue d’événements native.
  • Il n’y a pas d’événements AWT dans Java EventQueues.

Cornercases:

Le document indique que certains packages créent des composants affichables sans les libérer. Un programme qui appelle Toolkit.getDefaultToolkit () ne se terminera pas. est entre autres donné comme exemple.

D’autres processus peuvent également garder AWT en vie lorsqu’ils envoient des événements dans la queue d’événements native pour une raison quelconque.

J’ai également remarqué que sur certains systèmes, il faut quelques secondes avant que l’application se termine.

Je pense que l’idée est ici le WindowListener – vous pouvez y append n’importe quel code que vous souhaitez exécuter avant que la chose ne s’arrête

En réponse à d’autres commentaires, DISPOSE_ON_CLOSE ne semble pas quitter correctement l’application – elle ne détruit que la fenêtre, mais l’application continuera à s’exécuter. Si vous souhaitez terminer l’application, utilisez EXIT_ON_CLOSE.