web-dev-qa-db-fra.com

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 le déclenchement d'une minuterie. Mais appeler dispose() sur le JFrame n'a pas suffi - la fenêtre a disparu mais l'application ne s'est pas arrêtée. Cependant, lors de la fermeture de la fenêtre avec le bouton de fermeture, l'application se termine. Que devrais-je faire?

89

Votre action de fermeture par défaut dans JFrame peut être définie sur "DISPOSE_ON_CLOSE" Au lieu de EXIT_ON_CLOSE (La raison pour laquelle les utilisateurs continuent d'utiliser EXIT_ON_CLOSE me dépasse).

Si vous avez des fenêtres non affichées ou des threads non démon, 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 coupables les plus courants sont Java.util.Timer et un thread personnalisé que vous avez créé. Les deux doivent être configurés en démon ou doivent être explicitement supprimés.

Si vous voulez vérifier tous les cadres actifs, vous pouvez utiliser Frame.getFrames() . Si tous les Windows/Frames sont supprimés, utilisez un débogueur pour rechercher d'éventuels threads autres que des démons en cours d'exécution.

103
James Schek

Je suppose un EXIT_ON_CLOSE

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

before System.exit(0) est préférable, car vous pouvez écrire un Window Listener 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.");
}
34
VonC

Essayer:

System.exit(0);

Brut, mais efficace.

15
Daniel Spiewak

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

Le programme suivant comprend du code qui mettra fin à un programme dépourvu de threads superflus sans appeler explicitement System.exit (). Pour appliquer cet exemple aux applications utilisant des threads/listeners/timers/etc, il suffit d'insérer un code de nettoyage demandant (et, le cas échéant, en attente) leur arrêt 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 non pertinente 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(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
Eric Sadler

Si je vous ai bien compris, vous voulez fermer l'application même si l'utilisateur n'a pas cliqué sur le bouton de fermeture. Vous devrez peut-être enregistrer WindowEvents avec, par exemple, addWindowListener () ou enableEvents () selon vos besoins.

Vous pouvez ensuite appeler l'événement avec un appel à processWindowEvent (). Voici un exemple de code permettant de créer une image JFrame, d'attendre 5 secondes et de fermer l'image 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 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 constater, la méthode processWindowEvent () provoque le déclenchement de l'événement WindowClosed, ce qui vous permet d'effectuer un nettoyage du code si vous en avez besoin avant de fermer l'application.

4

Jetez un coup d’œil à Documentation Oracle .

À 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 file d'attente d'événements natifs.
  • Il n'y a pas d'événements AWT dans Java EventQueues.

Cornercules:

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

D'autres processus peuvent également maintenir AWT en vie lorsqu'ils, pour une raison quelconque, envoient des événements dans la file d'attente d'événements native.

De plus, j'ai remarqué que sur certains systèmes, il faut attendre quelques secondes avant que l'application se termine.

2
Reiner Lange

En réponse à d'autres commentaires, DISPOSE_ON_CLOSE ne semble pas quitter correctement l'application. Il ne fait que détruire la fenêtre, mais l'application continuera de s'exécuter. Si vous souhaitez mettre fin à l'application, utilisez EXIT_ON_CLOSE.

0
JSideris

Je pense que l'idée est ici WindowListener - vous pouvez ajouter n'importe quel code que vous voudriez exécuter avant que la chose s'arrête

0
Tamas Rev