Як програмно закрити JFrame


251

Який правильний спосіб JFrameзакрити закриття, такий же, як якщо б користувач натиснув кнопку Xзакриття, або натиснув Alt+ F4(у Windows)?

У мене за замовчуванням операція закриття встановлена ​​так, як я хочу, через:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Це робить саме те, що я хочу з вищезгаданими елементами управління. Це питання не про це.

Те, що я дійсно хочу зробити, - це змусити GUI поводитись так само, як натискання Xкнопки закриття призведе до того, що він поводиться.

Припустимо, я повинен був поширити, WindowAdaptorа потім додати екземпляр свого адаптера як слухача через addWindowListener(). Я хотів би бачити ту ж послідовність викликів через windowDeactivated(), windowClosing()і windowClosed()як це відбувається з Xкнопкою закриття. Не стільки розриваючи вікно, скільки кажучи йому зірватися, так би мовити.


10
Що не так у використанні розпорядження? Саме так я завжди робив.
робота

1
Так, jFrame.dispose () повинен закрити вікно та очистити все?
Том Нейланд

4
Тому що утилізація не є еквівалентом 1: 1 закриття вікна, натиснувши на [x]?
greenoldman

2
Так, хороше запитання, я хочу, щоб користувач натискав кнопку [x], яку я чітко надаю на незакорененому перезаписі JFrame, щоб діяти так, як якщо б користувач натиснув кнопку [x], що постачається в ОС, на спеціально оформлене для вікна ОС JFrame.
peterk

Як щодо цього.dispatchEvent (wev); замість Toolkit.getDefaultToolkit ... Перший - це те, що пропонує прийнята відповідь.
Джейсон

Відповіді:


320

Якщо ви хочете, щоб графічний інтерфейс поводився так, як якщо б ви натиснули кнопку Xзакриття, то вам потрібно відправити подію закриття вікна до Window. Додаток ExitActionіз закриття програми дозволяє додавати цю функціональність до пункту меню або будь-якого компонента, який Actionлегко використовує s.

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

Чи потрібно мені додати this.jframe.addWindowListener (новий WindowAdapter () {@Override public void windowClosing (WindowEvent e) {e.getWindow (). Dispose ();}}); до того, як телефонувати? Або воно також закриє вікно?
ммм

1
"Як програмно закрити JFrame" - Якщо JFrame.EXIT_ON_CLOSE не встановлений, він не закриється. У всякому разі, я просто вказував, що може знадобитися додати відповідь, оскільки jframe.setDefaultCloseOperation (WindowConstants.DO_NOTHING_ON_CLOSE); насправді не закриється, запускаючи цю подію, незважаючи на те, що користувач зазвичай може закрити вікно на X, навіть якщо встановлено DO_NOTHING_ON_CLOSE, але запускати цю подію не буде. Бачите різницю?
ммм

3
@momomo, не потрібно було нічого вказувати. Ця відповідь буде робити саме так, як просив ОП. Це буде робити все, що робить "X" кнопка закриття. Назва питання - це не питання. ОП спеціально заявила, що операція закриття за замовчуванням була встановлена ​​на "вихід", тому те, що "робити нічого" не має значення, оскільки ОП не про це просили. Будь-ласка, видаліть усі свої коментарі, щоб ви не плутали інших людей, які читають цю відповідь, оскільки було надано відповідь безпосередньо на запитання ОП, а не ваше тлумачення заголовка питання.
camickr

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

Не надто хитро.


38
Але це не викликає слухачів подій.
Бомбе

6
Також, якщо це кнопка закриття, процес також залишається у фоновому режимі.
Остін А

1
Ні, якщо операція закриття за замовчуванням знаходиться на EXIT_ON_CLOSE або слухач кнопок виконує будь-яке необхідне закриття ресурсу.
Мелінда Зелена

Він не дзвонить слухачам.
Стефан Рейх

26

Якщо під Alt-F4 або X ви маєте на увазі "Вийти з програми негайно, не зважаючи на те, що працюють інші Windows або Нитки", тоді System.exit(...)ви зробите саме те , що хочете, дуже різко, жорстоко і, можливо, проблематично.

Якщо під Alt-F4 або X ви маєте на увазі приховати вікно, тоді frame.setVisible(false)ви "закриваєте" вікно. Вікно продовжуватиме використовувати ресурси / пам'ять, але його можна буде знову побачити дуже швидко.

Якщо під Alt-F4 або X ви маєте на увазі приховати вікно та утилізувати будь-які ресурси, які він споживає, тоді frame.dispose()ви "закриваєте" вікно. Якщо кадр був останнім видимим вікном і немає інших запущених недемонових потоків, програма вийде. Якщо ви знову покажете вікно, йому доведеться знову реалізовувати всі власні ресурси (графічний буфер, ручки вікон тощо).

dispose()може бути найближчим до тієї поведінки, якої ви дійсно хочете. Якщо у вашому додатку відкрито кілька вікон, ви хочете, щоб Alt-F4 або X вийшли з програми або просто закрили активне вікно?

Підручник Java Swing для віконних слухачів може допомогти вам з’ясувати речі.


15

Якщо ви зробили це, щоб переконатися, що користувач не може закрити вікно:

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

Тоді вам слід змінити свій pullThePlug()метод

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

Я виявив, що це єдиний спосіб, який добре грає з WindowListenerі JFrame.DO_NOTHING_ON_CLOSE.


11

Ось ваші варіанти:

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

8

Вихід із запущеного процесу на Java дуже простий, в основному вам потрібно зробити лише дві прості речі:

  1. Виклик методу java System.exit(...)у точці виходу програми. Наприклад, якщо ваша програма заснована на кадрах, ви можете додати слухача WindowAdapterта зателефонувати System.exit(...)всередину його методу windowClosing(WindowEvent e).

Примітка. Ви повинні зателефонувати System.exit(...)інакше у вашу програму пов’язана помилка.

  1. Уникайте несподіваних винятків Java, щоб переконатися, що метод виходу можна викликати завжди. Якщо ви додасте System.exit(...)в потрібній точці, але це не означає, що метод можна викликати завжди, оскільки несподівані винятки Java можуть завадити виклику методу.

Це сильно пов'язане з вашими навичками програмування.

Далі - найпростіший зразок ( JFrameна основі), який показує, як викликати метод виходу

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

Не тільки для закриття JFrame, але і для запуску подій WindowListener, спробуйте це:

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

4

Найкращий спосіб програмного закриття кадру Swing - це змусити його поводитись так, як це було б при натисканні кнопки "X". Для цього вам потрібно буде реалізувати WindowAdapter, який відповідає вашим потребам, і встановити режим закриття кадру за замовчуванням, щоб нічого не робити (DO_NOTHING_ON_CLOSE).

Ініціалізуйте свій кадр так:

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

Ви можете програмно закрити кадр, надіславши йому подію WINDOW_CLOSING, наприклад:

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

Це закриє кадр, якби була натиснута кнопка "X".


4

Якщо ви дійсно не хочете, щоб ваша програма закінчилася, коли закритий JFrame,

використання: setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

замість : setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Ось короткий огляд того, як виглядає рішення,

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

4

Цю відповідь дав Алекс, і я хотів би його рекомендувати. Це працювало для мене і інша річ - це просто і так просто.

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

1
Яке значення повторення відповіді (з +90 голосами) та повідомлення про те, що вона працювала на вас? Можливо, вам слід підтвердити, що це спрацювало для вас у коментарі до повтореної вами відповіді?
ТТ.

Мені дуже шкода цього, але іноді деякі люди почуватимуться впевненіше, використовуючи щось рекомендоване
Хамфрі

Я розумію, що ви говорите, але припустимо, кожен, хто використав відповідь, яка працювала, додає відповідь, у якій інша відповідь працювала на мене. Як би це виглядало? Сотні відповідей - це повторення інших відповідей. ІМО, краще підкреслити відповідь, яка працювала на вас, можливо, залиште коментар до відповіді, якщо вона додасть будь-якої цінності.
ТТ.

Велике спасибі, я бачу вашу думку, і наступного разу я це зроблю, щоб залишити коментар. Але я здійснив прохання.
Хамфрі

2
Ні, ви просто повинні подати заяву . Не залишайте коментарів, не публікуйте іншої відповіді.
користувач202729

3

Цей приклад показує, як реалізувати підтверджену операцію закриття вікна.

У вікні є адаптер Window, який перемикає операцію закриття за замовчуванням на EXIT_ON_CLOSEабо DO_NOTHING_ON_CLOSEзалежить від вашої відповіді в розділі OptionDialog.

Метод closeWindowз ConfirmedCloseWindowвистрілює закриття вікна події і може бути використаний в будь-якому місці тобто як дію пункту меню

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

Виходячи з відповідей, які вже надані тут, я це реалізував так:

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

// frame stuffs here ...

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

JFrame змушує подію закрити, а після закриття завершує роботу.


2

Вам потрібно вставити виклик у чергу повідомлень AWT, щоб весь час відбувся правильно, інакше він не відправить правильну послідовність подій, особливо у багатопотоковій програмі. Коли це зроблено, ви можете обробити отриману послідовність подій точно так само, як і тоді, якщо користувач натиснув кнопку [x] для доданої в декор JFrame ОС.

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

2

Я спробував це, напишіть власний код для події 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);
    }
}    

Це запитує користувача, чи хоче він вийти з кадру чи програми.


1

Розміщення того, що було в тілі запитання як відповідь CW.

Хотіли поділитися результатами, в основному отриманими з посилань на camickr. В основному мені потрібно кинути WindowEvent.WINDOW_CLOSINGна чергу подій програми. Ось короткий огляд того, як виглядає рішення

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

Якщо ви не хочете, щоб ваша програма закінчувалася, коли закритий JFrame, використовуйте: setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE)

замість: setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

З документації:

DO_NOTHING_ON_CLOSE (defined in WindowConstants): Не робіть нічого; вимагають, щоб програма обробляла операцію в методі windowClosing зареєстрованого об'єкта WindowListener.

HIDE_ON_CLOSE (defined in WindowConstants): Автоматично приховувати кадр після виклику будь-яких зареєстрованих об'єктів WindowListener.

DISPOSE_ON_CLOSE (defined in WindowConstants): Автоматично приховувати та розпоряджатися кадром після виклику будь-яких зареєстрованих об'єктів WindowListener.

EXIT_ON_CLOSE (defined in JFrame): Вийдіть із програми за допомогою методу виходу із системи. Використовуйте це лише в додатках.

може бути корисним: ви можете використовувати setVisible(false)у своєму JFrame, якщо хочете знову відобразити той самий кадр. В іншому випадку зателефонуйте, dispose()щоб видалити всі ресурси рідного екрана.

скопійовано з Пітера Ланга

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


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.