Cómo cerrar programáticamente un JFrame

251

¿Cuál es la forma correcta JFramede cerrar, lo mismo que si el usuario hubiera presionado el Xbotón de cerrar o presionado Alt+ F4(en Windows)?

Tengo mi operación de cierre predeterminada configurada de la manera que quiero, a través de:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Hace exactamente lo que quiero con los controles antes mencionados. Esta pregunta no se trata de eso.

Lo que realmente quiero hacer es hacer que la GUI se comporte de la misma manera que presionar el Xbotón de cerrar haría que se comportara.

Supongamos que extiendo WindowAdaptory luego agrego una instancia de mi adaptador como un oyente a través de addWindowListener(). Me gustaría ver la misma secuencia de llamadas a través windowDeactivated(), windowClosing()y windowClosed()como ocurriría con el Xbotón de cierre. No tanto romper la ventana como decirle que se rompa, por así decirlo.

JustJeff
fuente
10
¿Qué hay de malo en usar dispose? Así es como siempre lo he hecho.
trabajo
1
Sí, jFrame.dispose () debería cerrar la ventana y limpiar todo.
Tom Neyland el
44
¿Porque disponer no es equivalente 1: 1 de cerrar la ventana haciendo clic en [x]?
greenoldman
2
Sí, buena pregunta, quiero que un usuario haga clic en un botón [x] que proporciono explícitamente en una anulación no decorada de un JFrame para que actúe exactamente como si el usuario hubiera hecho clic en el botón [x] proporcionado por el sistema operativo en una ventana JFrame decorada específica del sistema operativo.
peterk
¿Qué tal this.dispatchEvent (wev); en lugar de Toolkit.getDefaultToolkit ... El primero es lo que sugiere la respuesta aceptada.
Jason

Respuestas:

320

Si desea que la GUI se comporte como si hiciera clic en el Xbotón de cierre, debe enviar un evento de cierre de ventana al Window. El ExitActionde cerrar una aplicación le permite añadir esta funcionalidad a un elemento de menú o cualquier componente que utiliza Actions fácilmente.

frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
camickr
fuente
¿Debo agregar this.jframe.addWindowListener (new WindowAdapter () {@Override public void windowClosing (WindowEvent e) {e.getWindow (). Dispose ();}}); antes de llamar a esto? ¿O cerrará la ventana también?
mmm
1
"Cómo cerrar mediante programación un JFrame": si JFrame.EXIT_ON_CLOSE no está configurado, no se cerrará. De todos modos, solo estaba señalando que podría ser necesario agregar a la respuesta, ya que jframe.setDefaultCloseOperation (WindowConstants.DO_NOTHING_ON_CLOSE); en realidad no lo cerrará activando este evento a pesar de que el usuario normalmente puede cerrar la ventana en X incluso si DO_NOTHING_ON_CLOSE está configurado, pero disparar este evento no lo hará. ¿Ver la diferencia?
mmm
3
@momomo, no había necesidad de señalar nada. Esta respuesta hará exactamente lo que pidió el OP. Hará lo que haga el botón de cierre "X". El título de la pregunta no es la pregunta. El OP declaró específicamente que la operación de cierre predeterminada estaba configurada en "salir", por lo que lo que hace "no hacer nada" es irrelevante ya que el OP no estaba preguntando sobre eso. Elimine todos sus comentarios para no confundir a otras personas que leen esta respuesta, ya que la respuesta se dio para responder directamente la pregunta del OP, no su interpretación del encabezado de la pregunta.
camickr
131
setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object

No muy complicado.

Alex
fuente
38
Pero eso no llama a los oyentes de eventos.
Bombe
66
Además, si se trata de un botón de cierre, el proceso también se ejecuta en segundo plano.
Austin A
1
No si la operación de cierre predeterminada está en EXIT_ON_CLOSE o si el escucha del botón realiza el cierre de cualquier recurso necesario.
Melinda Green
No llama a los oyentes.
Stefan Reich
26

Si con Alt-F4 o X te refieres a "Salir de la aplicación inmediatamente sin tener en cuenta qué otras ventanas o subprocesos se están ejecutando", entonces System.exit(...)hará exactamente lo que quieras de una manera muy brusca, con fuerza bruta y posiblemente problemática.

Si con Alt-F4 o X te refieres a ocultar la ventana, entonces frame.setVisible(false)es cómo "cierras" la ventana. La ventana continuará consumiendo recursos / memoria, pero se puede volver a hacer visible muy rápidamente.

Si con Alt-F4 o X te refieres a ocultar la ventana y eliminar cualquier recurso que esté consumiendo, entonces frame.dispose()es cómo "cierras" la ventana. Si el marco era la última ventana visible y no hay otros subprocesos no daemon en ejecución, el programa se cerrará. Si vuelve a mostrar la ventana, tendrá que reinicializar todos los recursos nativos nuevamente (búfer de gráficos, identificadores de ventana, etc.).

dispose()podría estar más cerca del comportamiento que realmente quieres. Si su aplicación tiene varias ventanas abiertas, ¿desea que Alt-F4 o X salgan de la aplicación o simplemente cierren la ventana activa?

El Tutorial de Java Swing sobre Window Listeners puede ayudarlo a aclarar las cosas por usted.

James Schek
fuente
15

Si ha hecho esto para asegurarse de que el usuario no pueda cerrar la ventana:

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

Entonces deberías cambiar tu pullThePlug()método para ser

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

Encontré que esta es la única manera que juega bien con el WindowListenery JFrame.DO_NOTHING_ON_CLOSE.

Gazihan Alankus
fuente
11

Estas serían tus opciones:

System.exit(0); // stop program
frame.dispose(); // close window
frame.setVisible(false); // hide window
Aaron Esaú
fuente
8

Salir del proceso de ejecución de Java es muy fácil, básicamente debes hacer solo dos cosas simples:

  1. Llame al método java System.exit(...)en el punto de cierre de la aplicación. Por ejemplo, si su aplicación está basada en marcos, puede agregar oyente WindowAdaptery llamar System.exit(...)dentro de su método windowClosing(WindowEvent e).

Nota: debe llamar, de lo System.exit(...)contrario, su programa implica un error.

  1. Evitar excepciones inesperadas de Java para asegurarse de que siempre se pueda llamar al método de salida. Si agrega System.exit(...)en el punto correcto, pero no significa que se pueda llamar siempre al método, ya que las excepciones inesperadas de Java pueden evitar que se llame al método.

Esto está fuertemente relacionado con tus habilidades de programación.

** A continuación se muestra una muestra más simple ( JFramebasada) que muestra cómo llamar al método de salida

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

No solo para cerrar JFrame sino también para activar eventos WindowListener, intente esto:

myFrame.dispatchEvent(new WindowEvent(myFrame, WindowEvent.WINDOW_CLOSING));
niranaam
fuente
4

La mejor manera de cerrar un marco Swing mediante programación es hacer que se comporte como lo haría cuando se presiona el botón "X". Para hacerlo, deberá implementar WindowAdapter que se adapte a sus necesidades y establecer la operación de cierre predeterminada del marco para que no haga nada (DO_NOTHING_ON_CLOSE).

Inicialice su marco así:

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

Puede cerrar el marco mediante programación enviándole el evento WINDOW_CLOSING, de esta manera:

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

Esto cerrará el marco como se presionó el botón "X".

stjepano
fuente
4

Si realmente no desea que su aplicación finalice cuando se cierra un JFrame, entonces,

utilizar : setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

en vez de : setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Aquí hay una sinopsis de cómo se ve la solución,

 myFrame.dispatchEvent(new WindowEvent(myFrame, WindowEvent.WINDOW_CLOSING));
Harita M
fuente
4

Esta respuesta fue dada por Alex y me gustaría recomendarla. Funcionó para mí y otra cosa es sencilla y muy simple.

setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object
Humphrey
fuente
1
¿Cuál es el valor de repetir una respuesta (con +90 votos) y decir que funcionó para usted? ¿Quizás debería confirmar que funcionó para usted en un comentario sobre la respuesta que repitió?
TT.
Realmente lo siento mucho por eso, pero a veces algunas personas se sentirían más seguras de usar algo recomendado
Humphrey
Entiendo lo que está diciendo, pero supongamos que todos los que usaron una respuesta que funcionó agregan una respuesta que dice que la otra respuesta funcionó para mí. ¿Cómo se vería eso? Cientos de respuestas son una repetición de otras respuestas. En mi opinión, es mejor votar la respuesta que funcionó para usted, tal vez deje un comentario en la respuesta si agrega algún valor.
TT.
Muchas gracias. Veo tu punto y la próxima vez eso es lo que haré para dejar un comentario. Pero la votación lo hice.
Humphrey
2
No, solo deberías votar . No deje un comentario, no publique otra respuesta.
user202729
3

Este ejemplo muestra cómo realizar la operación de cierre de ventana confirmada.

La ventana tiene un adaptador de ventana que cambia la operación de cierre predeterminada EXIT_ON_CLOSEo DO_NOTHING_ON_CLOSEdepende de su respuesta en el OptionDialog.

El método closeWindowde ConfirmedCloseWindowdisparar un evento de cerrar ventana y puede usarse en cualquier lugar, es decir, como una acción de un elemento de menú

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
fuente
3

Según las respuestas que ya se proporcionan aquí, esta es la forma en que lo implementé:

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

// frame stuffs here ...

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

El JFrame cierra el evento y, al cerrar, sale.

Megatron
fuente
2

Debe insertar la llamada en la cola de mensajes de AWT para que todos los tiempos ocurran correctamente, de lo contrario no enviará la secuencia de eventos correcta, especialmente en un programa de subprocesos múltiples. Cuando se hace esto, puede manejar la secuencia de eventos resultante exactamente como lo haría si el usuario hubiera hecho clic en el botón [x] para un JFrame decorado con sistema operativo.

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

He intentado esto, escriba su propio código para el 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);
    }
}    

Esto le pregunta al usuario si quiere salir del Marco o la Aplicación.

r_D
fuente
1

Publicar lo que había en el cuerpo de la pregunta como respuesta de CW.

Quería compartir los resultados, principalmente derivados del siguiente enlace de camickr. Básicamente necesito lanzar un WindowEvent.WINDOW_CLOSINGen la cola de eventos de la aplicación. Aquí hay una sinopsis de cómo se ve la solución

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

Si no desea que su aplicación finalice cuando se cierra un JFrame, use: setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE)

en lugar de: setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

De la documentación:

DO_NOTHING_ON_CLOSE (defined in WindowConstants): No hagas nada; requiere que el programa maneje la operación en el método windowClosing de un objeto WindowListener registrado.

HIDE_ON_CLOSE (defined in WindowConstants): Ocultar automáticamente el marco después de invocar cualquier objeto registrado de WindowListener.

DISPOSE_ON_CLOSE (defined in WindowConstants): Oculta y desecha automáticamente el marco después de invocar cualquier objeto registrado de WindowListener.

EXIT_ON_CLOSE (defined in JFrame): Salga de la aplicación utilizando el método de salida del sistema. Use esto solo en aplicaciones.

aún puede ser útil: puede usarlo setVisible(false)en su JFrame si desea mostrar el mismo marco nuevamente. De lo contrario, llame dispose()para eliminar todos los recursos de la pantalla nativa.

copiado de Peter Lang

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

Mena Nashaat
fuente
0
 setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Itay Maman
fuente
Esto funcionaría en conjunto consetVisible(false) .setVisible(false); .setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Abhijeet