Come chiudere a livello di codice un JFrame


251

Qual è il modo corretto JFramedi chiudere, come se l'utente avesse Xpremuto il pulsante di chiusura o premuto Alt+ F4(su Windows)?

Ho la mia operazione di chiusura predefinita impostata nel modo desiderato, tramite:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Fa esattamente quello che voglio con i controlli di cui sopra. Questa domanda non riguarda questo.

Quello che voglio davvero fare è far sì che la GUI si comporti come Xfarebbe premendo un pulsante di chiusura.

Supponiamo che dovessi estendere WindowAdaptore quindi aggiungere un'istanza del mio adattatore come ascoltatore tramite addWindowListener(). Vorrei vedere la stessa sequenza di chiamate attraverso windowDeactivated(), windowClosing()e windowClosed()come avverrebbe con il Xpulsante di chiusura. Non tanto a strappare la finestra quanto a dirgli di strapparsi, per così dire.


10
Cosa c'è di sbagliato nell'uso di smaltimento? È così che l'ho sempre fatto.
lavoro

1
Sì, jFrame.dispose () dovrebbe chiudere la finestra e ripulire tutto?
Tom Neyland,

4
Perché disporre non equivale a 1: 1 per chiudere la finestra facendo clic su [x]?
Greenoldman,

2
Sì, bella domanda, voglio che un utente faccia clic su un pulsante [x] Fornisco esplicitamente su una sostituzione non decorata di un JFrame per agire esattamente come se l'utente avesse fatto clic sul pulsante [x] fornito dal sistema operativo su una finestra JFrame decorata specifica del sistema operativo.
Peter,

Che ne dici di this.dispatchEvent (wev); invece di Toolkit.getDefaultToolkit ... Il primo è ciò che suggerisce la risposta accettata.
Jason

Risposte:


320

Se si desidera che la GUI si comporti come se si fosse fatto clic sul Xpulsante Chiudi, è necessario inviare un evento di chiusura della finestra a Window. Il ExitActiondal Chiusura di un'applicazione consente di aggiungere questa funzionalità per una voce di menu o qualsiasi componente che utilizza Actions facilmente.

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

Devo aggiungere this.jframe.addWindowListener (new WindowAdapter () {@Override public void windowClosing (WindowEvent e) {e.getWindow (). Dispose ();}}); prima di chiamare questo? O chiuderà anche la finestra?
mmm,

1
"Come chiudere a livello di codice un JFrame" - Se JFrame.EXIT_ON_CLOSE non è impostato, non verrà chiuso. Ad ogni modo, stavo solo sottolineando che potrebbe essere necessario aggiungere la risposta, poiché jframe.setDefaultCloseOperation (WindowConstants.DO_NOTHING_ON_CLOSE); non lo chiuderà effettivamente attivando questo evento nonostante l'utente sia normalmente in grado di chiudere la finestra su X anche se DO_NOTHING_ON_CLOSE è impostato, ma l'attivazione di questo evento non lo farà. Vedi la differenza?
mmm,

3
@momo, non è stato necessario sottolineare nulla. Questa risposta farà esattamente come richiesto dall'OP. Farà qualunque cosa faccia il pulsante di chiusura "X". Il titolo della domanda non è la domanda. L'OP ha dichiarato specificamente che l'operazione di chiusura di default era impostata su "esci", quindi ciò che il "non fa nulla" è irrilevante poiché l'OP non lo stava chiedendo. Elimina tutti i tuoi commenti in modo da non confondere le altre persone che leggono questa risposta, poiché la risposta è stata data per rispondere direttamente alla domanda del PO, non alla tua interpretazione dell'intestazione della domanda.
Camickr,

131
setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object

Non troppo complicato.


38
Ma ciò non chiama i listener di eventi.
Bombe,

6
Inoltre, se si tratta di un pulsante di chiusura, il processo viene lasciato in esecuzione anche in background.
Austin,

1
Non se l'operazione di chiusura predefinita è su EXIT_ON_CLOSE o se il listener di pulsanti esegue la chiusura delle risorse necessaria.
Melinda Green,

Non chiama gli ascoltatori.
Stefan Reich,

26

Se per Alt-F4 o X intendi "Esci dall'applicazione immediatamente, indipendentemente da quali altre finestre o thread sono in esecuzione", allora System.exit(...)farà esattamente quello che vuoi in modo molto brusco, bruto e forse problematico.

Se per Alt-F4 o X intendi nascondere la finestra, allora frame.setVisible(false)è come "chiudi" la finestra. La finestra continuerà a consumare risorse / memoria ma può essere nuovamente visualizzata molto rapidamente.

Se per Alt-F4 o X intendi nascondere la finestra e smaltire tutte le risorse che sta consumando, allora frame.dispose()è come "chiudi" la finestra. Se il frame era l'ultima finestra visibile e non ci sono altri thread non daemon in esecuzione, il programma verrà chiuso. Se si visualizza nuovamente la finestra, sarà necessario reinizializzare nuovamente tutte le risorse native (buffer grafico, handle di finestra, ecc.).

dispose()potrebbe essere il più vicino al comportamento che desideri davvero. Se la tua app ha più finestre aperte, vuoi Alt-F4 o X per uscire dall'app o semplicemente chiudere la finestra attiva?

Il tutorial Java Swing su Window Listeners può aiutarti a chiarire le cose per te.


15

Se lo hai fatto per assicurarti che l'utente non possa chiudere la finestra:

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

Quindi dovresti cambiare il tuo pullThePlug()metodo

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); 
}

Ho trovato che questo è l'unico modo per giocare bene con WindowListenere JFrame.DO_NOTHING_ON_CLOSE.


11

Ecco le tue opzioni:

System.exit(0); // stop program
frame.dispose(); // close window
frame.setVisible(false); // hide window

8

Uscire dal processo di esecuzione di Java è molto semplice, in pratica devi fare solo due cose semplici:

  1. Chiama il metodo java System.exit(...)al punto di chiusura dell'applicazione. Ad esempio, se l'applicazione è basata su frame, è possibile aggiungere listener WindowAdaptere chiamare System.exit(...)nel suo metodo windowClosing(WindowEvent e).

Nota: devi chiamare System.exit(...)altrimenti il ​​tuo programma è coinvolto in errore.

  1. Evitare eccezioni java impreviste per assicurarsi che il metodo di uscita possa essere chiamato sempre. Se si aggiunge System.exit(...)al punto giusto, ma ciò non significa che il metodo può essere chiamato sempre, poiché eccezioni java impreviste potrebbero impedire la chiamata del metodo.

Questo è fortemente legato alle tue capacità di programmazione.

** Di seguito è riportato un esempio ( JFramebasato) più semplice che mostra come chiamare il metodo di uscita

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);
   }
}

7

Non solo per chiudere JFrame ma anche per attivare eventi WindowListener, prova questo:

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

4

Il modo migliore per chiudere un frame Swing a livello di codice è farlo funzionare come farebbe quando si preme il pulsante "X". Per fare ciò dovrai implementare WindowAdapter adatto alle tue esigenze e impostare l'operazione di chiusura predefinita del frame per non fare nulla (DO_NOTHING_ON_CLOSE).

Inizializza la cornice in questo modo:

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);
}

È possibile chiudere il frame a livello di codice inviandolo l'evento WINDOW_CLOSING, in questo modo:

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

Questo chiuderà il frame come il pulsante "X" è stato premuto.


4

Se davvero non vuoi che la tua applicazione venga chiusa alla chiusura di un JFrame,

uso : setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

invece di : setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Ecco una sinossi di come appare la soluzione,

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

4

Questa risposta è stata data da Alex e vorrei raccomandarla. Ha funzionato per me e un'altra cosa è semplice e così semplice.

setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object

1
Qual è il valore di ripetere una risposta (con +90 voti) e dire che ha funzionato per te? Forse dovresti confermare che ha funzionato per te in un commento sulla risposta che hai ripetuto?
TT.

Mi dispiace davvero tanto per quello, ma a volte alcune persone si sentono più sicure usando qualcosa raccomandato
Humphrey

Capisco quello che stai dicendo, ma suppongo che tutti quelli che hanno usato una risposta funzionante aggiungano una risposta dicendo che l'altra risposta ha funzionato per me. Come sarebbe? Centinaia di risposte sono una ripetizione di altre risposte. IMO è meglio votare la risposta che ha funzionato per te, magari lasciare un commento sulla risposta se aggiunge valore.
TT.

Grazie mille vedo il tuo punto e la prossima volta è quello che farò per lasciare un commento. Ma ho votato.
Humphrey,

2
No, dovresti solo votare . Non lasciare un commento, non pubblicare un'altra risposta.
user202729,

3

Questo esempio mostra come realizzare l'operazione di chiusura della finestra confermata.

La finestra ha un adattatore per finestra che commuta l'operazione di chiusura predefinita EXIT_ON_CLOSEo DO_NOTHING_ON_CLOSEdipende dalla tua risposta in OptionDialog.

Il metodo closeWindowdi ConfirmedCloseWindowgenera un evento di chiusura della finestra e può essere utilizzato ovunque, ad esempio come azione di una voce di 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));
    }
}

3

Sulla base delle risposte già fornite qui, questo è il modo in cui l'ho implementato:

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

// frame stuffs here ...

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

JFrame fa chiudere l'evento e alla chiusura esce.


2

Devi inserire la chiamata nella coda dei messaggi AWT in modo che tutti i tempi avvengano correttamente, altrimenti non invierà la sequenza di eventi corretta, specialmente in un programma multi-thread. Al termine, è possibile gestire la sequenza di eventi risultante esattamente come si farebbe se l'utente avesse fatto clic sul pulsante [x] per un JFrame decorato con SO integrato.

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

2

Ho provato questo, scrivere il proprio codice per l' evento 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);
    }
}    

Ciò chiede all'utente se desidera uscire dal frame o dall'applicazione.


1

Pubblicare ciò che era nel corpo della domanda come risposta in CW.

Volevo condividere i risultati, principalmente derivati ​​dal seguente link di Camickr. Fondamentalmente ho bisogno di lanciare un WindowEvent.WINDOW_CLOSINGnella coda degli eventi dell'applicazione. Ecco una sinossi di come appare la soluzione

// 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();

1

Se non si desidera che l'applicazione venga chiusa alla chiusura di un JFrame, utilizzare: setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE)

anziché: setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

Dalla documentazione:

DO_NOTHING_ON_CLOSE (defined in WindowConstants): Non fare nulla; richiede che il programma gestisca l'operazione nel metodo windowClosing di un oggetto WindowListener registrato.

HIDE_ON_CLOSE (defined in WindowConstants): Nasconde automaticamente la cornice dopo aver richiamato gli oggetti WindowListener registrati.

DISPOSE_ON_CLOSE (defined in WindowConstants): Nasconde e getta automaticamente la cornice dopo aver richiamato gli oggetti WindowListener registrati.

EXIT_ON_CLOSE (defined in JFrame): Consente di uscire dall'applicazione utilizzando il metodo di uscita Sistema. Usa questo solo nelle applicazioni.

potrebbe essere ancora utile: è possibile utilizzare setVisible(false)su JFrame se si desidera visualizzare nuovamente lo stesso frame. Altrimenti chiama dispose()per rimuovere tutte le risorse della schermata nativa.

copiato da Peter Lang

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


0
 setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

Ciò funzionerebbe in collaborazione consetVisible(false) .setVisible(false); .setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Abhijeet,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.