Como fechar programaticamente um JFrame

251

Qual é a maneira correta JFramede fechar um, da mesma forma que se o usuário tivesse pressionado o Xbotão Fechar ou pressionado Alt+ F4(no Windows)?

Tenho minha operação de fechamento padrão definida da maneira que desejo, via:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Faz exatamente o que eu quero com os controles acima mencionados. Esta questão não é sobre isso.

O que realmente quero fazer é fazer com que a GUI se comporte da mesma maneira que pressionar um botão XFechar faria com que ela se comportasse.

Suponha que eu estenda WindowAdaptore adicione uma instância do meu adaptador como ouvinte via addWindowListener(). Gostaria de ver a mesma seqüência de chamadas através windowDeactivated(), windowClosing()e windowClosed()como ocorreria com o Xbotão de fechar. Não tanto rasgar a janela como dizer para ela se rasgar, por assim dizer.

JustJeff
fonte
10
O que há de errado com o descarte? É assim que sempre faço.
job
1
Sim, o jFrame.dispose () deve fechar a janela e limpar tudo?
6116 Tom Neyland
4
Como descarte não é equivalente a 1: 1 do fechamento da janela clicando em [x]?
greenoldman
2
Sim, boa pergunta, quero que um usuário clique em um botão [x] que forneço explicitamente em uma substituição não decorada de um JFrame para agir exatamente como se o usuário tivesse clicado no botão [x] do SO fornecido em uma janela do JFrame decorada específica do SO.
Peterk 27/12/12
Que tal this.dispatchEvent (wev); em vez de Toolkit.getDefaultToolkit ... O primeiro é o que a resposta aceita sugere.
7773 Jason

Respostas:

320

Se você deseja que a GUI se comporte como se tivesse clicado no Xbotão Fechar, será necessário enviar um evento de fechamento de janela para o Window. A ExitActionpartir do fechamento de um aplicativo, você pode adicionar essa funcionalidade a um item de menu ou a qualquer componente que use Actions facilmente.

frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
camickr
fonte
Preciso adicionar this.jframe.addWindowListener (new WindowAdapter () {@Override public void windowClosing (WindowEvent e) {e.getWindow (). Dispose ();}}); antes de ligar para isso? Ou vai fechar a janela também?
mmm
1
"Como fechar programaticamente um JFrame" - Se o JFrame.EXIT_ON_CLOSE não estiver definido, ele não será fechado. Enfim, eu estava apenas apontando que talvez seja necessário adicionar à resposta, já que jframe.setDefaultCloseOperation (WindowConstants.DO_NOTHING_ON_CLOSE); não o fechará ativando esse evento, apesar de o usuário normalmente conseguir fechar a janela no X, mesmo que DO_NOTHING_ON_CLOSE esteja definido, mas o disparo desse evento não será. Veja a diferença?
mmm
3
@ Momomo, não havia necessidade de apontar nada. Essa resposta fará exatamente o que o OP pediu. Ele fará o que o botão "X" fechar. O título da pergunta não é a questão. O OP declarou especificamente que a operação de fechamento padrão foi definida como "exit" (saída); portanto, o que o "não fazer nada" faz é irrelevante, pois o OP não estava perguntando sobre isso. Exclua todos os seus comentários para não confundir outras pessoas que leem esta resposta, pois a resposta foi dada para responder diretamente à pergunta do OP, não à sua interpretação do cabeçalho da pergunta.
26617 camCam:
131
setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object

Não é muito complicado.

Alex
fonte
38
Mas isso não chama ouvintes de eventos.
Bombe
6
Além disso, se esse for um botão Fechar, o processo também será executado em segundo plano.
Austin A
1
Não se a operação de fechamento padrão estiver em EXIT_ON_CLOSE ou se o ouvinte de botão realizar qualquer fechamento de recurso necessário.
Melinda Green
Não chama os ouvintes.
Stefan Reich
26

Se, com Alt-F4 ou X, você quer dizer "Sair do aplicativo imediatamente, sem considerar o que outros Windows ou threads estão executando", System.exit(...)fará exatamente o que deseja de maneira muito brusca, de força bruta e possivelmente problemática.

Se por Alt-F4 ou X você quer dizer ocultar a janela, frame.setVisible(false)é assim que você "fecha" a janela. A janela continuará consumindo recursos / memória, mas poderá ser tornada visível novamente muito rapidamente.

Se por Alt-F4 ou X você quer dizer ocultar a janela e dispor de todos os recursos que está consumindo, frame.dispose()é assim que você "fecha" a janela. Se o quadro foi a última janela visível e não há outros threads que não sejam daemon em execução, o programa será encerrado. Se você exibir a janela novamente, será necessário reinicializar todos os recursos nativos novamente (buffer gráfico, identificadores de janela, etc.).

dispose()pode estar mais próximo do comportamento que você realmente deseja. Se o seu aplicativo tiver várias janelas abertas, você deseja que o Alt-F4 ou X saia do aplicativo ou simplesmente feche a janela ativa?

O tutorial do Java Swing nos ouvintes da janela pode ajudar a esclarecer as coisas para você.

James Schek
fonte
15

Se você fez isso para garantir que o usuário não possa fechar a janela:

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

Então você deve mudar seu 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); 
}

Eu achei que essa é a única maneira que funciona bem com o WindowListenere JFrame.DO_NOTHING_ON_CLOSE.

Gazihan Alankus
fonte
11

Aqui estão suas opções:

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

Sair do processo de execução do Java é muito fácil, basicamente você precisa fazer apenas duas coisas simples:

  1. Chame o método java System.exit(...)no ponto de encerramento do aplicativo. Por exemplo, se seu aplicativo for baseado em quadros, você poderá adicionar ouvinte WindowAdaptere chamar System.exit(...)dentro de seu método windowClosing(WindowEvent e).

Nota: você deve ligar System.exit(...)caso contrário, seu programa está envolvido com erros.

  1. Evitando exceções java inesperadas para garantir que o método de saída possa ser chamado sempre. Se você adicionar System.exit(...)no ponto certo, mas isso não significa que o método possa ser chamado sempre, pois exceções java inesperadas podem impedir que o método seja chamado.

Isso está fortemente relacionado às suas habilidades de programação.

** A seguir, é apresentado um exemplo mais simples ( JFramebaseado) que mostra como chamar o método de saída

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

Não apenas para fechar o JFrame, mas também para acionar os eventos WindowListener, tente o seguinte:

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

A melhor maneira de fechar programaticamente um quadro oscilante é fazê-lo se comportar como faria quando o botão "X" for pressionado. Para fazer isso, você precisará implementar o WindowAdapter que atenda às suas necessidades e definir a operação de fechamento padrão do quadro para não fazer nada (DO_NOTHING_ON_CLOSE).

Inicialize seu quadro assim:

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

Você pode fechar o quadro programaticamente enviando o evento WINDOW_CLOSING, desta forma:

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

Isso fechará o quadro como se o botão "X" fosse pressionado.

stjepano
fonte
4

Se você realmente não deseja que seu aplicativo seja encerrado quando um JFrame for fechado,

usar : setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

ao invés de : setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Aqui está uma sinopse da aparência da solução,

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

Esta resposta foi dada por Alex e eu gostaria de recomendá-la. Funcionou para mim e outra coisa é direta e simples.

setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object
Humphrey
fonte
1
Qual é o valor de repetir uma resposta (com +90 votos) e dizer que funcionou para você? Talvez você deva confirmar que funcionou para você em um comentário sobre a resposta que repetiu?
TT.
Estou realmente muito triste por isso, mas, por vezes, algumas pessoas se sentem mais confiantes usando algo recomendado
Humphrey
Entendo o que você está dizendo, mas suponha que todos que usaram uma resposta que funcionou adicionem uma resposta dizendo que a outra resposta funcionou para mim. Como isso seria? Centenas de respostas sendo uma repetição de outras respostas. Na IMO, é melhor aprovar a resposta que funcionou para você, talvez deixe um comentário sobre a resposta se ela agregar algum valor.
TT.
Muito obrigado. Entendo seu ponto de vista e, da próxima vez, é o que farei para deixar um comentário. Mas voto positivo eu fiz.
Humphrey
2
Não, você deve apenas votar . Não deixe um comentário, não poste outra resposta.
User202729
3

Este exemplo mostra como realizar a operação de fechamento de janela confirmada.

A janela possui um adaptador de janela que alterna a operação de fechamento padrão para EXIT_ON_CLOSEou DO_NOTHING_ON_CLOSEdepende da sua resposta no OptionDialog.

O método closeWindowdo ConfirmedCloseWindowacionamento de um evento de janela fechada e pode ser usado em qualquer lugar, ou seja, como uma ação de um item de 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
fonte
3

Com base nas respostas já fornecidas aqui, é assim que eu a implementei:

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

// frame stuffs here ...

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

O JFrame faz com que o evento seja fechado e, ao fechar, sai.

Megatron
fonte
2

É necessário inserir a chamada na fila de mensagens do AWT para que todo o tempo ocorra corretamente, caso contrário não enviará a sequência de eventos correta, especialmente em um programa multiencadeado. Quando isso for feito, você poderá manipular a sequência de eventos resultante exatamente como faria se o usuário clicasse no botão [x] para um JFrame decorado com SO fornecido.

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

Eu tentei isso, escreva seu próprio código para o 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);
    }
}    

Isso pergunta ao usuário se ele deseja sair do quadro ou do aplicativo.

r_D
fonte
1

Publicando o que estava no corpo da pergunta como resposta da CW.

Queria compartilhar os resultados, derivados principalmente do seguinte link do camickr. Basicamente, eu preciso jogar um WindowEvent.WINDOW_CLOSINGna fila de eventos do aplicativo. Aqui está uma sinopse da aparência da solução

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

Se você não deseja que seu aplicativo seja encerrado quando um JFrame estiver fechado, use: setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE)

em vez de: setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

A partir da documentação:

DO_NOTHING_ON_CLOSE (defined in WindowConstants): Não faça nada; requer que o programa manipule a operação no método windowClosing de um objeto WindowListener registrado.

HIDE_ON_CLOSE (defined in WindowConstants): Oculte automaticamente o quadro depois de chamar qualquer objeto WindowListener registrado.

DISPOSE_ON_CLOSE (defined in WindowConstants): Oculte e descarte automaticamente o quadro depois de chamar qualquer objeto WindowListener registrado.

EXIT_ON_CLOSE (defined in JFrame): Saia do aplicativo usando o método de saída do sistema. Use isso apenas em aplicativos.

ainda pode ser útil: você pode usar setVisible(false)no seu JFrame se desejar exibir o mesmo quadro novamente. Caso contrário, chame dispose()para remover todos os recursos da tela nativa.

copiado de Peter Lang

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

Mena Nashaat
fonte
0
 setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Itay Maman
fonte
Isso funcionaria em conjunto comsetVisible(false) .setVisible(false); .setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Abhijeet