Comment fermer une application Java Swing à partir du code

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

j'ai essayé de fermer mon application automatiquement après le déclenchement d'une minuterie. Mais simplement appeler dispose() sur le JFrame n'a pas fait l'affaire - la fenêtre a disparu mais l'application n'a pas pris fin. Toutefois, lors de la fermeture de la fenêtre avec le bouton Fermer, l'application se termine. Que dois-je faire?

86
demandé sur hstoerr 2008-11-03 11:01:53

9 réponses

votre action de fermeture par défaut JFrame peut être définie à 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 threads windows ou non-démon non-affichés, votre application ne se terminera pas. Cela devrait être considéré comme une erreur (et la résoudre avec le système.la sortie est une très mauvaise idée).

les coupables les plus courants sont java.util.Minuterie et un fil personnalisé que vous avez créé. Les deux doivent être réglés à ou démon doit être explicitement tué.

si vous voulez vérifier tous les cadres actifs, vous pouvez utiliser Frame.getFrames() . Si tous les fenêtres / cadres sont éliminés, utilisez un débogueur pour vérifier s'il y a des threads Non-daemon qui sont encore en cours d'exécution.

101
répondu James Schek 2008-11-06 15:22:25

I guess a EXIT_ON_CLOSE

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

avant System.exit(0) est mieux car vous pouvez écrire un écouteur de fenêtre pour faire quelques opérations de nettoyage avant de réellement quitter l'application.

cette fenêtre d'écoute 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.");
}
34
répondu VonC 2008-11-03 08:21:25

, Essayez:

System.exit(0);

brut, mais efficace.

12
répondu Daniel Spiewak 2008-11-03 08:04:31

peut - être que le chemin 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();
        }
    });
11
répondu Kachwahed 2013-02-08 16:18:46

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

pour ceux qui souhaitent copier / coller du code capable de fonctionner exactement comme montré, une méthode principale légèrement laid mais par ailleurs non pertinent est inclus à 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(String[] 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);
            }
        });
    }
}
9
répondu Eric Sadler 2013-06-23 14:41:02

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

, Vous pouvez alors invoquer l'événement avec un appel à processWindowEvent(). Voici un exemple de code qui va créer un JFrame, attendre 5 secondes et fermer le JFrame sans interaction avec 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 interested 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(String args[]){
          new ClosingFrame();
    }

}

comme vous pouvez le voir, la méthode processWindowEvent() provoque le déclenchement de L'événement WindowClosed lorsque vous avez la possibilité de faire du code de nettoyage si vous en avez besoin avant de fermer l'application.

4
répondu Vincent Ramdhanie 2008-11-03 08:41:10

regardez la Oracle Documentation .

à partir de JDK 1.4 une Application se termine si:

  • il n'y a pas de composantes AWT ou Swing amovibles.
  • il n'y a pas d'événements autochtones dans la file d'attente des événements autochtones.
  • il n'y a pas d'événements AWT dans java EventQueues.

Cornercases:

le document indique que certains paquets créent des composants déplaçables sans les libérer. un programme qui appelle Toolkit.getDefaultToolkit () ne se terminera pas. est un exemple parmi d'autres.

aussi d'autres processus peuvent garder AWT vivant quand ils, pour quelque raison que ce soit, envoient des événements dans la file d'attente d'événements natifs.

J'ai aussi remarqué que sur certains systèmes, il faut un coup de secondes avant que l'Application se termine.

2
répondu Reiner Lange 2013-09-25 11:32:19

je pense, l'idée est ici le WindowListener - vous pouvez y ajouter n'importe quel code que vous souhaitez exécuter avant que la chose se ferme

0
répondu Tamas Rev 2010-01-18 21:44:51

en réponse à d'autres commentaires, DISPOSE_ON_CLOSE ne semble pas sortir correctement de l'application - il détruit seulement la fenêtre, mais l'application va continuer à tourner. Si vous voulez mettre fin à l'application utilisez EXIT_ON_CLOSE.

0
répondu JSideris 2011-08-16 00:37:34