Comment fermer par programme un JFrame

251

Quelle est la bonne façon d'obtenir une JFramefermeture, la même chose que si l'utilisateur avait Xappuyé sur le bouton de fermeture ou appuyé sur Alt+ F4(sous Windows)?

J'ai mon opération de fermeture par défaut définie comme je le souhaite, via:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Il fait exactement ce que je veux avec les commandes susmentionnées. Cette question n'est pas à ce sujet.

Ce que je veux vraiment faire, c'est que l'interface graphique se comporte de la même manière qu'une pression sur le Xbouton de fermeture la ferait se comporter.

Supposons que je devais étendre WindowAdaptorpuis ajouter une instance de mon adaptateur comme écouteur via addWindowListener(). Je voudrais voir la même séquence d'appels à travers windowDeactivated(), windowClosing()et windowClosed()comme cela se produirait avec le Xbouton de fermeture. Pas tant pour déchirer la fenêtre que pour lui dire de se déchirer, pour ainsi dire.

JustJeff
la source
10
Quel est le problème avec l'utilisation de disposer? C'est comme ça que je l'ai toujours fait.
job
1
Ouais, jFrame.dispose () devrait fermer la fenêtre et tout nettoyer?
Tom Neyland
4
Parce que disposer n'est pas l'équivalent de 1: 1 de fermer la fenêtre en cliquant sur [x]?
greenoldman
2
Oui bonne question, je veux qu'un utilisateur clique sur un bouton [x] que je fournis explicitement sur un remplacement non décoré d'un JFrame pour agir exactement comme si l'utilisateur avait cliqué sur le bouton [x] fourni par l'OS sur une fenêtre JFrame décorée spécifique à l'OS.
peterk
Que diriez-vous de this.dispatchEvent (wev); au lieu de Toolkit.getDefaultToolkit ... Le premier est ce que la réponse acceptée suggère.
Jason

Réponses:

320

Si vous souhaitez que l'interface graphique se comporte comme si vous avez cliqué sur le Xbouton Fermer, vous devez envoyer un événement de fermeture de fenêtre au Window. À ExitActionpartir de la fermeture d'une application, vous pouvez ajouter cette fonctionnalité à un élément de menu ou à tout composant qui utilise Actionfacilement s.

frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
camickr
la source
Dois-je ajouter this.jframe.addWindowListener (new WindowAdapter () {@Override public void windowClosing (WindowEvent e) {e.getWindow (). Dispose ();}}); avant d'appeler cela? Ou fermera-t-il également la fenêtre?
mmm
1
"Comment fermer un JFrame par programme" - Si le JFrame.EXIT_ON_CLOSE n'est pas défini, il ne se fermera pas. Quoi qu'il en soit, je soulignais simplement qu'il pourrait être nécessaire d'ajouter à la réponse, car jframe.setDefaultCloseOperation (WindowConstants.DO_NOTHING_ON_CLOSE); ne le fermera pas réellement en déclenchant cet événement bien que l'utilisateur puisse normalement fermer la fenêtre sur X même si DO_NOTHING_ON_CLOSE est défini, mais le déclenchement de cet événement ne le fera pas. Regarde la différence?
mmm
3
@momomo, il n'était pas nécessaire de signaler quoi que ce soit. Cette réponse fera exactement ce que l'OP a demandé. Il fera tout ce que fait le bouton de fermeture "X". Le titre de la question n'est pas la question. L'OP a spécifiquement déclaré que l'opération de fermeture par défaut était définie sur "exit", donc ce que fait le "ne rien faire" n'est pas pertinent puisque l'OP ne posait pas de question à ce sujet. Veuillez supprimer tous vos commentaires afin de ne pas confondre les autres personnes qui lisent cette réponse, car la réponse a été donnée pour répondre directement à la question du PO, pas votre interprétation du titre de la question.
camickr
131
setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object

Pas trop compliqué.

Alex
la source
38
Mais cela n'appelle pas les auditeurs d'événements.
Bombe
6
De plus, s'il s'agit d'un bouton de fermeture, le processus est également exécuté en arrière-plan.
Austin A
1
Pas si l'opération de fermeture par défaut est sur EXIT_ON_CLOSE ou si l'écouteur de bouton effectue la fermeture de ressource nécessaire.
Melinda Green
Il n'appelle pas les auditeurs.
Stefan Reich
26

Si par Alt-F4 ou X vous voulez dire "Quittez l'application immédiatement sans tenir compte des autres fenêtres ou threads en cours d'exécution", alors vous System.exit(...)ferez exactement ce que vous voulez d'une manière très abrupte, brutale et éventuellement problématique.

Si par Alt-F4 ou X vous voulez dire cacher la fenêtre, frame.setVisible(false)c'est comme ça que vous "fermez" la fenêtre. La fenêtre continuera à consommer des ressources / mémoire mais peut être rendue visible à nouveau très rapidement.

Si par Alt-F4 ou X vous voulez dire cacher la fenêtre et disposer de toutes les ressources qu'elle consomme, alors frame.dispose()comment "fermer" la fenêtre. Si le cadre était la dernière fenêtre visible et qu'aucun autre thread non démon n'est en cours d'exécution, le programme se fermera. Si vous affichez à nouveau la fenêtre, elle devra réinitialiser à nouveau toutes les ressources natives (tampon graphique, poignées de fenêtre, etc.).

dispose()pourrait être le plus proche du comportement que vous voulez vraiment. Si votre application a plusieurs fenêtres ouvertes, voulez-vous que Alt-F4 ou X quitte l'application ou ferme tout simplement la fenêtre active?

Le tutoriel Java Swing sur les écouteurs de fenêtre peut aider à clarifier les choses pour vous.

James Schek
la source
15

Si vous avez fait cela pour vous assurer que l'utilisateur ne peut pas fermer la fenêtre:

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

Ensuite, vous devez changer votre pullThePlug()méthode pour être

public void pullThePlug() {
    // this will make sure WindowListener.windowClosing() et al. will be called.
    WindowEvent wev = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);

    // this will hide and dispose the frame, so that the application quits by
    // itself if there is nothing else around. 
    setVisible(false);
    dispose();
    // if you have other similar frames around, you should dispose them, too.

    // finally, call this to really exit. 
    // i/o libraries such as WiiRemoteJ need this. 
    // also, this is what swing does for JFrame.EXIT_ON_CLOSE
    System.exit(0); 
}

J'ai trouvé que c'était la seule façon de bien jouer avec WindowListeneret JFrame.DO_NOTHING_ON_CLOSE.

Gazihan Alankus
la source
11

Voici vos options:

System.exit(0); // stop program
frame.dispose(); // close window
frame.setVisible(false); // hide window
Aaron Esau
la source
8

Quitter le processus d'exécution Java est très simple, vous devez simplement faire deux choses simples:

  1. Appelez la méthode java System.exit(...)au point de fermeture de l'application. Par exemple, si votre application est basée sur un cadre, vous pouvez ajouter un écouteur WindowAdapteret appeler System.exit(...)dans sa méthode windowClosing(WindowEvent e).

Remarque: vous devez appeler System.exit(...)sinon votre programme est une erreur impliquée.

  1. Éviter les exceptions Java inattendues pour vous assurer que la méthode de sortie peut toujours être appelée. Si vous ajoutez System.exit(...)au bon moment, mais cela ne signifie pas que la méthode peut toujours être appelée, car des exceptions Java inattendues peuvent empêcher l'appel de la méthode.

Ceci est fortement lié à vos compétences en programmation.

** Voici un exemple le plus simple ( JFramebasé) qui vous montre comment appeler la méthode de sortie

import java.awt.event.*;
import javax.swing.*;

public class ExitApp extends JFrame
{
   public ExitApp()
   {
      addWindowListener(new WindowAdapter()
      {
         public void windowClosing(WindowEvent e)
         {
           dispose();
           System.exit(0); //calling the method is a must
         }
      });
   }

   public static void main(String[] args)
   {
      ExitApp app=new ExitApp();
      app.setBounds(133,100,532,400);
      app.setVisible(true);
   }
}
Jaimin Patel
la source
7

Non seulement pour fermer le JFrame mais aussi pour déclencher des événements WindowListener, essayez ceci:

myFrame.dispatchEvent(new WindowEvent(myFrame, WindowEvent.WINDOW_CLOSING));
niranaam
la source
4

La meilleure façon de fermer un cadre Swing par programmation est de le faire se comporter comme il le ferait lorsque le bouton "X" est enfoncé. Pour ce faire, vous devrez implémenter WindowAdapter qui convient à vos besoins et définir l'opération de fermeture par défaut du cadre pour ne rien faire (DO_NOTHING_ON_CLOSE).

Initialisez votre cadre comme ceci:

private WindowAdapter windowAdapter = null;

private void initFrame() {

    this.windowAdapter = new WindowAdapter() {
        // WINDOW_CLOSING event handler
        @Override
        public void windowClosing(WindowEvent e) {
            super.windowClosing(e);
            // You can still stop closing if you want to
            int res = JOptionPane.showConfirmDialog(ClosableFrame.this, "Are you sure you want to close?", "Close?", JOptionPane.YES_NO_OPTION);
            if ( res == 0 ) {
                // dispose method issues the WINDOW_CLOSED event
                ClosableFrame.this.dispose();
            }
        }

        // WINDOW_CLOSED event handler
        @Override
        public void windowClosed(WindowEvent e) {
            super.windowClosed(e);
            // Close application if you want to with System.exit(0)
            // but don't forget to dispose of all resources 
            // like child frames, threads, ...
            // System.exit(0);
        }
    };

    // when you press "X" the WINDOW_CLOSING event is called but that is it
    // nothing else happens
    this.setDefaultCloseOperation(ClosableFrame.DO_NOTHING_ON_CLOSE);
    // don't forget this
    this.addWindowListener(this.windowAdapter);
}

Vous pouvez fermer le cadre par programme en lui envoyant l'événement WINDOW_CLOSING, comme ceci:

WindowEvent closingEvent = new WindowEvent(targetFrame, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(closingEvent);

Cela fermera le cadre comme si le bouton "X" était enfoncé.

stjepano
la source
4

Si vous ne voulez vraiment pas que votre application se termine lorsqu'un JFrame est fermé, alors,

utilisation : setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

au lieu de : setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Voici un synopsis de ce à quoi ressemble la solution,

 myFrame.dispatchEvent(new WindowEvent(myFrame, WindowEvent.WINDOW_CLOSING));
Harita M
la source
4

Cette réponse a été donnée par Alex et je voudrais la recommander. Cela a fonctionné pour moi et une autre chose est simple et si simple.

setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object
Humphrey
la source
1
Quelle est la valeur de répéter une réponse (avec +90 votes) et de dire que cela a fonctionné pour vous? Peut-être devriez-vous confirmer que cela a fonctionné pour vous dans un commentaire sur la réponse que vous avez répétée?
TT.
Je suis vraiment désolé pour cela, mais parfois certaines personnes se sentiraient plus en confiance en utilisant quelque chose de recommandé
Humphrey
Je comprends ce que vous dites, mais supposez que tous ceux qui ont utilisé une réponse qui a fonctionné ajoutent une réponse disant que l'autre réponse a fonctionné pour moi. À quoi cela ressemblerait-il? Des centaines de réponses étant une répétition d'autres réponses. OMI, il est préférable de voter pour la réponse qui a fonctionné pour vous, peut-être de laisser un commentaire sur la réponse si elle ajoute une valeur.
TT.
Merci beaucoup je vois votre point et la prochaine fois c'est ce que je vais faire pour laisser un commentaire. Mais j'ai voté.
Humphrey
2
Non, vous devriez juste voter . Ne laissez pas de commentaire, ne postez pas de réponse.
user202729
3

Cet exemple montre comment réaliser l'opération de fermeture de fenêtre confirmée.

La fenêtre possède un adaptateur de fenêtre qui bascule l'opération de fermeture par défaut vers EXIT_ON_CLOSEou en DO_NOTHING_ON_CLOSEfonction de votre réponse dans le OptionDialog.

La méthode closeWindowde ConfirmedCloseWindowdéclenche un événement de fermeture de fenêtre et peut être utilisée n'importe où, c'est-à-dire comme action d'un élément de menu

public class WindowConfirmedCloseAdapter extends WindowAdapter {

    public void windowClosing(WindowEvent e) {

        Object options[] = {"Yes", "No"};

        int close = JOptionPane.showOptionDialog(e.getComponent(),
                "Really want to close this application?\n", "Attention",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.INFORMATION_MESSAGE,
                null,
                options,
                null);

        if(close == JOptionPane.YES_OPTION) {
           ((JFrame)e.getSource()).setDefaultCloseOperation(
                   JFrame.EXIT_ON_CLOSE);
        } else {
           ((JFrame)e.getSource()).setDefaultCloseOperation(
                   JFrame.DO_NOTHING_ON_CLOSE);
        }
    }
}

public class ConfirmedCloseWindow extends JFrame {

    public ConfirmedCloseWindow() {

        addWindowListener(new WindowConfirmedCloseAdapter());
    }

    private void closeWindow() {
        processWindowEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
    }
}
rkd
la source
3

Sur la base des réponses déjà fournies ici, voici comment je l'ai implémenté:

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

// frame stuffs here ...

frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));

Le JFrame obtient la fermeture de l'événement et à la fermeture, quitte.

Megatron
la source
2

Vous devez insérer l'appel dans la file d'attente de messages AWT pour que tout le timing se déroule correctement, sinon il ne distribuera pas la séquence d'événements correcte, en particulier dans un programme multithread. Lorsque cela est fait, vous pouvez gérer la séquence d'événements résultante exactement comme vous le feriez si l'utilisateur a cliqué sur le bouton [x] pour un JFrame décoré fourni par le système d'exploitation.

public void closeWindow()
{
    if(awtWindow_ != null) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                awtWindow_.dispatchEvent(new WindowEvent(awtWindow_, WindowEvent.WINDOW_CLOSING));
            }
        });
    }
}
peterk
la source
2

J'ai essayé cela, écrivez votre propre code pour l' événement formWindowClosing () .

 private void formWindowClosing(java.awt.event.WindowEvent evt) {                                   
    int selectedOption = JOptionPane.showConfirmDialog(null,
            "Do you want to exit?",
            "FrameToClose",
            JOptionPane.YES_NO_OPTION);
    if (selectedOption == JOptionPane.YES_OPTION) {
        setVisible(false);
        dispose();
    } else {
        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
    }
}    

Cela demande à l'utilisateur s'il souhaite quitter le cadre ou l'application.

r_D
la source
1

Publier ce qui était dans le corps de la question comme réponse CW.

Je voulais partager les résultats, principalement dérivés du lien suivant de camickr. Fondamentalement, je dois lancer un WindowEvent.WINDOW_CLOSINGdans la file d'attente d'événements de l'application. Voici un synopsis de ce à quoi ressemble la solution

// closing down the window makes sense as a method, so here are
// the salient parts of what happens with the JFrame extending class ..

    public class FooWindow extends JFrame {
        public FooWindow() {
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setBounds(5, 5, 400, 300);  // yeah yeah, this is an example ;P
            setVisible(true);
        }
        public void pullThePlug() {
                WindowEvent wev = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
                Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);
        }
    }

// Here's how that would be employed from elsewhere -

    // someplace the window gets created ..
    FooWindow fooey = new FooWindow();
    ...
    // and someplace else, you can close it thusly
    fooey.pullThePlug();
Vogel612
la source
1

Si vous ne souhaitez pas que votre application se termine à la fermeture d'un JFrame, utilisez: setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE)

au lieu de: setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

De la documentation:

DO_NOTHING_ON_CLOSE (defined in WindowConstants): Ne faites rien; exiger que le programme gère l'opération dans la méthode windowClosing d'un objet WindowListener enregistré.

HIDE_ON_CLOSE (defined in WindowConstants): Masquer automatiquement le cadre après avoir appelé tous les objets WindowListener enregistrés.

DISPOSE_ON_CLOSE (defined in WindowConstants): Masque et supprime automatiquement le cadre après avoir appelé tous les objets WindowListener enregistrés.

EXIT_ON_CLOSE (defined in JFrame): Quittez l'application à l'aide de la méthode de sortie du système. Utilisez-le uniquement dans les applications.

peut encore être utile: vous pouvez utiliser setVisible(false)sur votre JFrame si vous souhaitez afficher à nouveau le même cadre. Sinon, appelez dispose()pour supprimer toutes les ressources d'écran natives.

copié de Peter Lang

https://stackoverflow.com/a/1944474/3782247

Mena Nashaat
la source
0
 setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Itay Maman
la source
Cela fonctionnerait en conjonction avecsetVisible(false) .setVisible(false); .setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Abhijeet