Как программно закрыть JFrame


251

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

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

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Это делает именно то, что я хочу с вышеупомянутыми элементами управления. Этот вопрос не об этом.

Что я действительно хочу сделать, так это заставить графический интерфейс вести себя так же, как нажатие Xкнопки закрытия приведет к его поведению.

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


10
Что не так с использованием утилизации? Я всегда так делал.
работа

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

4
Поскольку утилизация не является 1: 1 эквивалентом закрытия окна, нажав на [x]?
Гринольдман

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

Как насчет this.dispatchEvent (wev); вместо Toolkit.getDefaultToolkit ... Первое, что предлагает принятый ответ.
Джейсон

Ответы:


320

Если вы хотите, чтобы графический интерфейс вел себя так, как будто вы нажали Xкнопку закрытия, вам нужно отправить событие закрытия окна в Window. ExitActionОт закрытия приложения позволяет добавить эту функцию в пункт меню или любой компонент , который использует Actions легко.

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

Нужно ли добавлять this.jframe.addWindowListener (new 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 вы имеете в виду «Немедленно выйти из приложения, безотносительно к тому, что работают другие окна или потоки», тогда вы System.exit(...)будете делать именно то , что вам нужно, очень резким, грубым и, возможно, проблематичным образом.

Если под Alt-F4 или X вы подразумеваете скрытие окна, то frame.setVisible(false)это то, как вы «закрываете» окно. Окно будет продолжать использовать ресурсы / память, но его можно будет снова быстро увидеть.

Если под Alt-F4 или X вы имеете в виду скрыть окно и утилизировать все ресурсы, которые оно потребляет, то frame.dispose()это то, как вы «закрываете» окно. Если кадр был последним видимым окном и не запущены другие потоки, не являющиеся демонами, программа завершится. Если вы снова откроете окно, ему придется заново инициализировать все собственные ресурсы (графический буфер, дескрипторы окон и т. Д.).

dispose()может быть ближе всего к поведению, которое вы действительно хотите. Если в вашем приложении открыто несколько окон, хотите ли вы, чтобы Alt-F4 или X закрыли приложение или просто закрыли активное окно?

Java Swing Учебник по Window Слушатели могут помочь прояснить вещи для вас.


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 голосами) и говорить, что он работает для вас? Возможно, вам следует подтвердить, что это сработало для вас в комментарии к ответу, который вы повторили?
ТТ.

Я действительно очень сожалею об этом, но иногда некоторые люди чувствуют себя более уверенно, используя что-то рекомендованное
Хамфри

Я понимаю, что вы говорите, но предположим, что каждый, кто использовал сработавший ответ, добавляет ответ, что другой ответ сработал для меня. Как это будет выглядеть? Сотни ответов являются повторением других ответов. IMO, лучше поднять голос, который сработал для вас, возможно, оставьте комментарий к ответу, если он добавляет какую-либо ценность.
ТТ.

Большое спасибо, я понимаю вашу точку зрения, и в следующий раз это то, что я сделаю, чтобы оставить комментарий. Но голосование я сделал.
Хамфри

2
Нет, ты должен просто поддержать . Не оставляйте комментарий, не оставляйте другой ответ.
user202729

3

Этот пример показывает, как реализовать подтвержденную операцию закрытия окна.

В окне есть оконный адаптер, который переключает операцию закрытия по умолчанию 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


0
 setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

Это будет работать в сочетании сsetVisible(false) .setVisible(false); .setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Abhijeet
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.