So schließen Sie einen JFrame programmgesteuert


251

Was ist der richtige Weg, um eine JFramezu schließen, genauso als ob der Benutzer die XSchaltfläche zum Schließen gedrückt oder Alt+ F4(unter Windows) gedrückt hätte ?

Ich habe meine Standard-Schließoperation so eingestellt, wie ich es möchte:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Mit den oben genannten Steuerelementen macht es genau das, was ich will. Bei dieser Frage geht es nicht darum.

Was ich wirklich tun möchte, ist, dass sich die GUI genauso verhält wie ein Druck auf die XSchaltfläche "Schließen".

Angenommen, ich würde WindowAdaptoreine Instanz meines Adapters als Listener über erweitern und dann hinzufügen addWindowListener(). Ich möchte die gleiche Reihenfolge der Anrufe durch , um zu sehen windowDeactivated(), windowClosing()und windowClosed()wie bei der auftreten würde XSchließen - Schaltfläche. Das Fenster nicht so sehr aufreißen, als dass es sich sozusagen aufreißen soll.


10
Was ist falsch an der Verwendung von Dispose? So habe ich es immer gemacht.
Job

1
Ja, jFrame.dispose () sollte das Fenster schließen und alles aufräumen?
Tom Neyland

4
Weil Dispose nicht 1: 1 dem Schließen des Fensters durch Klicken auf [x] entspricht?
Greenoldman

2
Ja, gute Frage, ich möchte, dass ein Benutzer auf eine [x] -Schaltfläche klickt, die ich explizit bei einer nicht dekorierten Überschreibung eines JFrames angegeben habe, um genau so zu handeln , als hätte der Benutzer in einem betriebssystemspezifisch dekorierten JFrame-Fenster auf die vom Betriebssystem bereitgestellte Schaltfläche [x] geklickt.
Peterk

Wie wäre es mit this.dispatchEvent (wev); anstelle von Toolkit.getDefaultToolkit ... Ersteres wird in der akzeptierten Antwort vorgeschlagen.
Jason

Antworten:


320

Wenn Sie möchten, dass sich die GUI so verhält, als hätten Sie auf die XSchaltfläche zum Schließen geklickt , müssen Sie ein Ereignis zum Schließen des Fensters an die senden Window. Mit " ExitActionVom Schließen einer Anwendung" können Sie diese Funktionalität einem Menüelement oder einer Komponente hinzufügen, die Actions problemlos verwendet.

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

Muss ich this.jframe.addWindowListener hinzufügen (neuer WindowAdapter () {@Override public void windowClosing (WindowEvent e) {e.getWindow (). Dispose ();}}); bevor Sie dies anrufen? Oder wird es auch das Fenster schließen?
mmm

1
"So schließen Sie einen JFrame programmgesteuert" - Wenn JFrame.EXIT_ON_CLOSE nicht festgelegt ist, wird es nicht geschlossen. Wie auch immer, ich habe nur darauf hingewiesen, dass es möglicherweise erforderlich sein könnte, die Antwort zu ergänzen, da jframe.setDefaultCloseOperation (WindowConstants.DO_NOTHING_ON_CLOSE); schließt es nicht durch Auslösen dieses Ereignisses, obwohl der Benutzer normalerweise das Fenster auf X schließen kann, selbst wenn DO_NOTHING_ON_CLOSE gesetzt ist, aber das Auslösen dieses Ereignisses nicht. Sieh den Unterschied?
mmm

3
@momomo, es war nicht nötig, auf irgendetwas hinzuweisen. Diese Antwort entspricht genau den Anforderungen des OP. Es wird alles tun, was die Schaltfläche "X" zum Schließen tut. Der Titel der Frage ist nicht die Frage. Das OP gab ausdrücklich an, dass die Standardschließoperation auf "Beenden" gesetzt wurde. Was das "Nichts tun" tut, ist daher irrelevant, da das OP nicht danach gefragt hat. Bitte löschen Sie alle Ihre Kommentare, damit Sie andere Personen, die diese Antwort lesen, nicht verwirren, da die Antwort gegeben wurde, um die Frage des OP direkt zu beantworten, nicht Ihre Interpretation der Überschrift der Frage.
Camickr

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

Nicht zu knifflig.


38
Das nennt aber keine Ereignis-Listener.
Bombe

6
Wenn dies eine Schaltfläche zum Schließen wäre, wird der Prozess auch im Hintergrund ausgeführt.
Austin A

1
Nicht, wenn die Standardschließoperation EXIT_ON_CLOSE ist oder der Schaltflächenlistener das Schließen der erforderlichen Ressourcen ausführt.
Melinda Green

Es ruft die Zuhörer nicht an.
Stefan Reich

26

Wenn Sie mit Alt-F4 oder X "Beenden Sie die Anwendung sofort, ohne Rücksicht darauf, was andere Windows oder Threads ausführen" meinen, dann System.exit(...)tun Sie genau das , was Sie wollen, auf sehr abrupte, brutale und möglicherweise problematische Weise.

Wenn Sie mit Alt-F4 oder X das Fenster ausblenden meinen, frame.setVisible(false)schließen Sie das Fenster auf diese Weise. Das Fenster verbraucht weiterhin Ressourcen / Speicher, kann jedoch sehr schnell wieder sichtbar gemacht werden.

Wenn Sie mit Alt-F4 oder X das Fenster ausblenden und alle verbrauchten Ressourcen entsorgen möchten, frame.dispose()schließen Sie das Fenster auf diese Weise. Wenn der Frame das letzte sichtbare Fenster war und keine anderen Nicht-Daemon-Threads ausgeführt werden, wird das Programm beendet. Wenn Sie das Fenster erneut anzeigen, müssen alle nativen Ressourcen (Grafikpuffer, Fensterhandles usw.) erneut initialisiert werden.

dispose()ist möglicherweise dem Verhalten am nächsten, das Sie wirklich wollen. Wenn in Ihrer App mehrere Fenster geöffnet sind, möchten Sie, dass Alt-F4 oder X die App beenden oder einfach das aktive Fenster schließen?

Das Java Swing-Lernprogramm für Fensterlistener kann Ihnen dabei helfen, die Dinge für Sie zu klären.


15

Wenn Sie dies getan haben, um sicherzustellen, dass der Benutzer das Fenster nicht schließen kann:

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

Dann sollten Sie Ihre pullThePlug()Methode ändern

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

Ich fand, dass dies der einzige Weg ist, der gut mit dem WindowListenerund spielt JFrame.DO_NOTHING_ON_CLOSE.


11

Hier wären Ihre Optionen:

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

8

Das Beenden des Java-Ausführungsprozesses ist sehr einfach. Grundsätzlich müssen Sie nur zwei einfache Dinge tun:

  1. Rufen Sie die Java-Methode System.exit(...)am Beendigungspunkt der Anwendung auf. Wenn Ihre Anwendung beispielsweise rahmenbasiert ist, können Sie Listener hinzufügen WindowAdapterund System.exit(...)innerhalb ihrer Methode aufrufen windowClosing(WindowEvent e).

Hinweis: Sie müssen aufrufen, da System.exit(...)sonst Ihr Programm fehlerhaft ist.

  1. Vermeiden Sie unerwartete Java-Ausnahmen, um sicherzustellen, dass die Exit-Methode immer aufgerufen werden kann. Wenn Sie System.exit(...)an der richtigen Stelle hinzufügen , bedeutet dies jedoch nicht, dass die Methode immer aufgerufen werden kann, da unerwartete Java-Ausnahmen den Aufruf der Methode verhindern können.

Dies hängt stark mit Ihren Programmierkenntnissen zusammen.

** Im Folgenden finden Sie ein einfachstes Beispiel ( JFramebasierend), das Ihnen zeigt, wie Sie die Exit-Methode aufrufen

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

Versuchen Sie Folgendes, um nicht nur den JFrame zu schließen, sondern auch WindowListener-Ereignisse auszulösen:

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

4

Der beste Weg, einen Swing-Frame programmgesteuert zu schließen, besteht darin, ihn so zu verhalten, als würde er sich beim Drücken der Taste "X" verhalten. Dazu müssen Sie WindowAdapter implementieren, das Ihren Anforderungen entspricht, und die Standard-Schließoperation des Frames so einstellen, dass nichts unternommen wird (DO_NOTHING_ON_CLOSE).

Initialisieren Sie Ihren Frame wie folgt:

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

Sie können den Frame programmgesteuert schließen, indem Sie ihm das Ereignis WINDOW_CLOSING wie folgt senden:

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

Dadurch wird der Rahmen geschlossen, als ob die Taste "X" gedrückt wurde.


4

Wenn Sie wirklich nicht möchten, dass Ihre Anwendung beendet wird, wenn ein JFrame geschlossen wird, dann

verwenden : setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

anstatt : setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Hier ist eine Übersicht darüber, wie die Lösung aussieht:

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

4

Diese Antwort wurde von Alex gegeben und ich möchte sie empfehlen. Es hat bei mir funktioniert und eine andere Sache ist einfach und so einfach.

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

1
Welchen Wert hat es, eine Antwort (mit +90 Stimmen) zu wiederholen und zu sagen, dass sie für Sie funktioniert hat? Vielleicht sollten Sie in einem Kommentar zu der Antwort, die Sie wiederholt haben, bestätigen, dass es für Sie funktioniert hat?
TT.

Das tut mir wirklich sehr leid, aber manchmal fühlen sich einige Leute
Humphrey,

Ich verstehe, was Sie sagen, aber nehmen wir an, jeder, der eine funktionierende Antwort verwendet hat, fügt eine Antwort hinzu, die besagt, dass die andere Antwort für mich funktioniert hat. Wie würde das aussehen? Hunderte von Antworten wiederholen andere Antworten. IMO ist es besser, die Antwort, die für Sie funktioniert hat, zu verbessern. Vielleicht hinterlassen Sie einen Kommentar zu der Antwort, wenn sie einen Mehrwert bietet.
TT.

Vielen Dank, ich verstehe Ihren Standpunkt und das nächste Mal werde ich tun, um einen Kommentar zu hinterlassen. Aber ich habe es getan.
Humphrey

2
Nein, du solltest einfach upvoten . Hinterlasse keinen Kommentar, poste keine weitere Antwort.
user202729

3

Dieses Beispiel zeigt, wie der bestätigte Fensterschließvorgang realisiert wird.

Das Fenster verfügt über einen Fensteradapter, der den Standard- Schließvorgang auf Ihre Antwort in der EXIT_ON_CLOSEoder in DO_NOTHING_ON_CLOSEAbhängigkeit von dieser umschaltet OptionDialog.

Die Methode closeWindow des ConfirmedCloseWindowfeuert ein Fenster schließen Ereignis und kann überall dh als Aktion eines Menüpunktes verwendet werden

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

Basierend auf den hier bereits gegebenen Antworten habe ich dies folgendermaßen implementiert:

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

// frame stuffs here ...

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

Der JFrame bringt das Ereignis zum Schließen und wird beim Schließen beendet.


2

Sie müssen den Anruf in die AWT-Nachrichtenwarteschlange einfügen, damit das gesamte Timing korrekt abläuft. Andernfalls wird nicht die richtige Ereignissequenz ausgelöst, insbesondere in einem Multithread-Programm. Wenn dies erledigt ist, können Sie die resultierende Ereignissequenz genau so behandeln, als ob der Benutzer auf die Schaltfläche [x] für einen vom Betriebssystem unterstützten dekorierten JFrame geklickt hätte.

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

2

Ich habe dies versucht, schreibe deinen eigenen Code für das Ereignis 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);
    }
}    

Dadurch wird der Benutzer gefragt, ob er den Frame oder die Anwendung beenden möchte.


1

Posten, was sich im Fragenkörper befand, als CW-Antwort.

Wollte die Ergebnisse teilen, die hauptsächlich aus dem folgenden Link von camickr stammen. Grundsätzlich muss ich ein WindowEvent.WINDOW_CLOSINGin die Ereigniswarteschlange der Anwendung werfen . Hier ist eine Zusammenfassung, wie die Lösung aussieht

// 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

Wenn Sie nicht möchten, dass Ihre Anwendung beendet wird, wenn ein JFrame geschlossen wird, verwenden Sie: setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE)

anstelle von: setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

Aus der Dokumentation:

DO_NOTHING_ON_CLOSE (defined in WindowConstants): Tu nichts; Das Programm muss die Operation in der windowClosing-Methode eines registrierten WindowListener-Objekts ausführen.

HIDE_ON_CLOSE (defined in WindowConstants): Versteckt den Frame automatisch, nachdem registrierte WindowListener-Objekte aufgerufen wurden.

DISPOSE_ON_CLOSE (defined in WindowConstants): Verstecken und entsorgen Sie den Frame automatisch, nachdem Sie registrierte WindowListener-Objekte aufgerufen haben.

EXIT_ON_CLOSE (defined in JFrame): Beenden Sie die Anwendung mit der System-Exit-Methode. Verwenden Sie dies nur in Anwendungen.

könnte immer noch nützlich sein: Sie können setVisible(false)auf Ihrem JFrame verwenden, wenn Sie denselben Frame erneut anzeigen möchten. Andernfalls rufen Sie dispose()auf, um alle nativen Bildschirmressourcen zu entfernen.

kopiert von Peter Lang

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


0
 setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

Dies würde in Verbindung mitsetVisible(false) .setVisible(false); .setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Abhijeet
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.