Jak programowo zamknąć JFrame

251

Jaki jest właściwy sposób na JFramezamknięcie, tak samo, jakby użytkownik nacisnął Xprzycisk zamykania lub nacisnął Alt+ F4(w systemie Windows)?

Mam domyślną operację zamykania ustawioną tak, jak chcę:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Robi dokładnie to, co chcę z wyżej wspomnianymi kontrolkami. To pytanie nie dotyczy tego.

Naprawdę chcę zrobić, aby GUI zachowywał się w taki sam sposób, jak naciśnięcie Xprzycisku zamykania spowodowałoby jego zachowanie.

Załóżmy, że mam rozszerzyć, WindowAdaptora następnie dodać instancję mojego adaptera jako odbiornika za pośrednictwem addWindowListener(). Chciałbym zobaczyć tę samą sekwencję połączeń za pośrednictwem windowDeactivated(), windowClosing()i windowClosed()co miałoby miejsce przy Xścisłej przycisku. Nie tyle łzawienie w okno, ale mówienie mu, żeby się rozerwało.

JustJeff
źródło
10
Co jest złego w korzystaniu z dispose? Tak zawsze to robiłem.
praca
1
Tak, jFrame.dispose () powinien zamknąć okno i wszystko wyczyścić?
Tom Neyland,
4
Ponieważ opcja dispose nie jest odpowiednikiem zamknięcia okna w stosunku 1: 1 poprzez kliknięcie na [x]?
greenoldman,
2
Tak dobre pytanie, chcę, aby użytkownik kliknął przycisk [x], który jawnie podaję w nieudokumentowanym zastąpieniu JFrame, aby działał dokładnie tak, jakby użytkownik kliknął dostarczony przez system operacyjny przycisk [x] w ozdobnym oknie JFrame dla określonego systemu operacyjnego.
peterk
Co powiesz na this.dispatchEvent (wev); zamiast Toolkit.getDefaultToolkit ... To pierwsze sugeruje zaakceptowana odpowiedź.
Jason

Odpowiedzi:

320

Jeśli chcesz, aby GUI zachowywał się tak, jakbyś kliknął Xprzycisk zamykania, musisz wysłać do zdarzenia zdarzenia zamknięcia okna Window. ExitActionZ zamknięciem aplikacji pozwala na dodanie tej funkcji do pozycji menu lub jakiegokolwiek komponentu, który wykorzystuje Actions łatwo.

frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
camickr
źródło
Czy muszę dodać this.jframe.addWindowListener (new WindowAdapter () {@Override public void windowClosing (WindowEvent e) {e.getWindow (). Dispose ();}}); przed wywołaniem tego? Czy też zamknie okno?
mmm
1
„Jak programowo zamknąć JFrame” - Jeśli JFrame.EXIT_ON_CLOSE nie jest ustawiony, nie zostanie zamknięty. W każdym razie, właśnie wskazałem, że może być konieczne dodanie odpowiedzi, ponieważ jframe.setDefaultCloseOperation (WindowConstants.DO_NOTHING_ON_CLOSE); tak naprawdę nie zamknie go przez wywołanie tego zdarzenia, mimo że użytkownik zwykle może zamknąć okno na X, nawet jeśli jest ustawiony DO_NOTHING_ON_CLOSE, ale uruchomienie tego zdarzenia nie. Zobacz różnicę?
mmm
3
@momomo, nie trzeba było niczego wskazywać. Ta odpowiedź będzie działać dokładnie tak, jak poprosił PO. Zrobi wszystko, co robi przycisk zamykania „X”. Tytuł pytania nie jest pytaniem. OP konkretnie stwierdził, że domyślna operacja zamykania została ustawiona na „wyjście”, więc to, co robi „nic nie rób”, jest nieistotne, ponieważ OP nie pyta o to. Usuń wszystkie swoje komentarze, aby nie pomylić innych osób czytających tę odpowiedź, ponieważ odpowiedź została udzielona, ​​aby bezpośrednio odpowiedzieć na pytanie PO, a nie twoją interpretację nagłówka pytania.
camickr
131
setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object

Niezbyt trudne.

Alex
źródło
38
Ale to nie wywołuje detektorów zdarzeń.
Bombe,
6
Ponadto, jeśli byłby to przycisk zamykania, proces również pozostaje uruchomiony w tle.
Austin A
1
Nie, jeśli domyślną operacją zamykania jest EXIT_ON_CLOSE lub nasłuchiwanie przycisku wykonuje wymagane zamknięcie zasobu.
Melinda Green,
Nie dzwoni do słuchaczy.
Stefan Reich
26

Jeśli przez Alt-F4 lub X masz na myśli „Natychmiastowe zamknięcie aplikacji bez względu na to, jakie inne systemy Windows lub wątki są uruchomione ”, wtedy System.exit(...)zrobisz dokładnie to , co chcesz w bardzo gwałtowny, brutalny sposób i być może problematyczne.

Jeśli przez Alt-F4 lub X masz na myśli ukrywanie okna, frame.setVisible(false)oznacza to, jak „zamykasz” okno. Okno będzie nadal zużywać zasoby / pamięć, ale może być bardzo szybko ponownie widoczne.

Jeśli przez Alt-F4 lub X masz na myśli ukrycie okna i pozbycie się wszystkich zasobów, które zużywa, to w frame.dispose()ten sposób „zamykasz” okno. Jeśli ramka była ostatnim widocznym oknem i nie działają żadne inne wątki niebędące demonami, program zakończy działanie. Jeśli ponownie wyświetlisz okno, konieczne będzie ponowne zainicjowanie wszystkich zasobów natywnych (bufor graficzny, uchwyty okna itp.).

dispose()może być najbliższe zachowaniu, którego naprawdę chcesz. Jeśli w Twojej aplikacji jest otwartych wiele okien, czy chcesz, aby Alt-F4 lub X zamknęły aplikację lub po prostu zamknęły aktywne okno?

Java Swing Tutorial na Słuchaczy okienne mogą pomóc wyjaśnić rzeczy dla Ciebie.

James Schek
źródło
15

Jeśli to zrobiłeś, aby upewnić się, że użytkownik nie może zamknąć okna:

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

Następnie powinieneś zmienić pullThePlug()metodę na

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

Uważam, że jest to jedyny sposób, że odgrywa ładne z WindowListeneri JFrame.DO_NOTHING_ON_CLOSE.

Gazihan Alankus
źródło
11

Oto twoje opcje:

System.exit(0); // stop program
frame.dispose(); // close window
frame.setVisible(false); // hide window
Aaron Ezaw
źródło
8

Wyjście z uruchomionego procesu Java jest bardzo łatwe, w zasadzie musisz zrobić tylko dwie proste rzeczy:

  1. Wywołaj metodę Java System.exit(...)w punkcie wyjścia aplikacji. Na przykład, jeśli twoja aplikacja jest oparta na ramkach, możesz dodać detektor WindowAdapteri wywołać System.exit(...)jego metodę windowClosing(WindowEvent e).

Uwaga: musisz zadzwonić, w System.exit(...)przeciwnym razie w twoim programie występuje błąd.

  1. Unikanie nieoczekiwanych wyjątków Java, aby mieć pewność, że metoda wyjścia może być zawsze wywoływana. Jeśli dodasz System.exit(...)w odpowiednim momencie, ale nie oznacza to, że można zawsze wywoływać metodę, ponieważ nieoczekiwane wyjątki Java mogą uniemożliwić wywołanie metody.

Jest to ściśle związane z umiejętnościami programistycznymi.

** Poniżej znajduje się najprostsza próbka ( JFrameoparta), która pokazuje, jak wywołać metodę wyjścia

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
źródło
7

Spróbuj nie tylko zamknąć JFrame, ale także wywołać zdarzenia WindowListener:

myFrame.dispatchEvent(new WindowEvent(myFrame, WindowEvent.WINDOW_CLOSING));
niranaam
źródło
4

Najlepszym sposobem na programowe zamknięcie ramki Swing jest sprawienie, aby zachowywała się tak, jak po naciśnięciu przycisku „X”. Aby to zrobić, musisz zaimplementować WindowAdapter, który odpowiada twoim potrzebom i ustawić domyślną operację zamykania ramki, aby nic nie robić (DO_NOTHING_ON_CLOSE).

Zainicjuj ramkę w następujący sposób:

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

Możesz zamknąć ramkę programowo, wysyłając do niej zdarzenie WINDOW_CLOSING, w następujący sposób:

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

Spowoduje to zamknięcie ramki po naciśnięciu przycisku „X”.

stjepano
źródło
4

Jeśli naprawdę nie chcesz, aby aplikacja zakończyła się po zamknięciu JFrame,

posługiwać się : setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

zamiast : setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Oto streszczenie tego rozwiązania,

 myFrame.dispatchEvent(new WindowEvent(myFrame, WindowEvent.WINDOW_CLOSING));
Harita M.
źródło
4

Ta odpowiedź została udzielona przez Alexa i chciałbym ją polecić. To zadziałało dla mnie i kolejna rzecz jest prosta i taka prosta.

setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object
Humphrey
źródło
1
Jaka jest wartość powtarzania odpowiedzi (z +90 głosami) i mówienia, że ​​zadziałała dla Ciebie? Być może powinieneś potwierdzić, że zadziałało to w komentarzu do odpowiedzi, którą powtórzyłeś?
TT.
Bardzo mi przykro z tego powodu, ale czasami niektórzy ludzie czują się pewniej, używając czegoś zalecanego
Humphrey,
Rozumiem, co mówisz, ale załóżmy, że każdy, kto użył odpowiedzi, która zadziałała, dodaje odpowiedź mówiącą, że druga odpowiedź działała dla mnie. Jak by to wyglądało? Setki odpowiedzi są powtórzeniem innych odpowiedzi. IMO lepiej jest głosować na odpowiedź, która Ci się przydała, może zostawić komentarz do odpowiedzi, jeśli wnosi ona jakąkolwiek wartość.
TT.
Wielkie dzięki, rozumiem twój punkt widzenia i następnym razem to zrobię, aby zostawić komentarz. Ale zrobiłem to pozytywnie.
Humphrey,
2
Nie, powinieneś po prostu głosować . Nie zostawiaj komentarza, nie publikuj innej odpowiedzi.
user202729,
3

Ten przykład pokazuje, jak zrealizować operację potwierdzonego zamknięcia okna.

Okno ma adapter Windows, który przełącza domyślną operację zamykania na EXIT_ON_CLOSElub DO_NOTHING_ON_CLOSEzależy od twojej odpowiedzi w OptionDialog.

Metoda closeWindowz ConfirmedCloseWindowwystrzeliwuje Zamknij okno zdarzenie i może być stosowany wszędzie czyli jako działanie elementu 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
źródło
3

W oparciu o udzielone już odpowiedzi w ten sposób go zaimplementowałem:

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

// frame stuffs here ...

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

JFrame powoduje zamknięcie zdarzenia, a po zamknięciu wyjście.

Megatron
źródło
2

Musisz wstawić wywołanie do kolejki komunikatów AWT, aby wszystkie czasy działały poprawnie, w przeciwnym razie nie wywoła prawidłowej sekwencji zdarzeń, szczególnie w programie wielowątkowym. Po wykonaniu tej czynności możesz obsługiwać wynikową sekwencję zdarzeń dokładnie tak, jak gdyby użytkownik kliknął przycisk [x], aby uzyskać ozdobioną JFrame dla systemu operacyjnego.

public void closeWindow()
{
    if(awtWindow_ != null) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                awtWindow_.dispatchEvent(new WindowEvent(awtWindow_, WindowEvent.WINDOW_CLOSING));
            }
        });
    }
}
peterk
źródło
2

Próbowałem tego, napisz swój kod dla zdarzenia 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);
    }
}    

Pyta użytkownika, czy chce wyjść z ramki lub aplikacji.

r & D
źródło
1

Publikowanie tego, co było w treści pytania jako odpowiedzi CW.

Chciałem udostępnić wyniki, pochodzące głównie z linku prowadzącego camickr. Zasadniczo muszę rzucić WindowEvent.WINDOW_CLOSINGw kolejkę zdarzeń aplikacji. Oto streszczenie tego rozwiązania

// 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
źródło
1

Jeśli nie chcesz, aby aplikacja zakończyła się po zamknięciu JFrame, użyj: setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE)

zamiast: setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

Z dokumentacji:

DO_NOTHING_ON_CLOSE (defined in WindowConstants): Nic nie rób; wymagać od programu obsługi operacji w metodzie windowClosing zarejestrowanego obiektu WindowListener.

HIDE_ON_CLOSE (defined in WindowConstants): Automatycznie ukryj ramkę po wywołaniu dowolnego zarejestrowanego obiektu WindowListener.

DISPOSE_ON_CLOSE (defined in WindowConstants): Automatycznie ukryj i usuń ramkę po wywołaniu dowolnego zarejestrowanego obiektu WindowListener.

EXIT_ON_CLOSE (defined in JFrame): Zamknij aplikację, korzystając z metody wyjścia System. Używaj tego tylko w aplikacjach.

może być nadal przydatny: możesz użyć setVisible(false)w JFrame, jeśli chcesz ponownie wyświetlić tę samą ramkę. W przeciwnym razie wywołaj, dispose()aby usunąć wszystkie rodzime zasoby ekranu.

skopiowane z Peter Lang

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

Mena Nashaat
źródło
0
 setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Itay Maman
źródło
Działałoby to w połączeniu zsetVisible(false) .setVisible(false); .setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Abhijeet,