Usar WindowEvent para questionar o fechamento de um JFrame

Pessoal, estava usando o WindowEvent e o WindowListener para criar uma ação onde quando a pessoa fosse fechar o JFrame lhe fosse questionado se a pessoa queria mesmo fechar.

Assim:


    JFrame.addWindowListener(new java.awt.event.WindowAdapter(){
        public void windowClosing(java.awt.event.WindowEvent e){
            if(e.getID() == WindowEvent.WINDOW_CLOSING){
                int selectedOption = JOptionPane.showConfirmDialog(null, "Tem certeza que quer fechar?",
                "Fechar",
                JOptionPane.OK_CANCEL_OPTION,
                JOptionPane.QUESTION_MESSAGE);
            if(selectedOption == JOptionPane.OK_OPTION){
                System.exit(0);
            }    
            }
        }
    });

Porem apareceu um erro dizendo:
“non-static method addWindowListener(WindowListener) cannot be referenced from a static context”

Alguém poderia me ajudar?

Você está tentando chamar o método addWindowListener de forma estática, isto é NomeDaClasse.nomeDoMetodo , entretanto esse método não é estático, então você precisa chamar ele a partir de um objeto e não a partir da classe.

2 curtidas

Eu entendi o erro, mas não consigo entender como “escapar” dele. Comecei a estudar java há pouquíssimo tempo.
Obrigado.

Só dá pra escapar do erro, entendendo ele de fato.
Ao invés de chamar o método addWindowListener a partir da classe, chame a partir do objeto daquela classe.

Suponho que você implementou algo assim:

JFrame meuObjeto = new JFrame("Minha janela");
JFrame.addWindowListener(new WindowAdapter(){

    public void windowClosing(WindowEvent e){
        sair();
    }
});

O correto é assim:

JFrame meuObjeto = new JFrame("Minha janela");
meuObjeto.addWindowListener(new WindowAdapter(){

    public void windowClosing(WindowEvent e){
        sair();
    }
});

Outra coisa, você implementou seu WindowListener assim:

public void windowClosing(WindowEvent e){
    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
        int option = JOptionPane.showConfirmDialog(null,
                                                   "Tem certeza que quer fechar?",
                                                   "Fechar",
                                                   JOptionPane.OK_CANCEL_OPTION,
                                                   JOptionPane.QUESTION_MESSAGE);
        if (option == JOptionPane.OK_OPTION){
            System.exit(0);
        }    
    }
}

Não é necessário testar se o ID do evento é igual à WindowEvent.WINDOW_CLOSING pois você já está tratando o evento windowClosing da interface WindowListener.
O AWT/Swing só vão invocar este método quando ocorrer um WindowEventdo tipo WINDOW_CLOSING.
Faça simplesmente assim:

public void windowClosing(WindowEvent e){
    sair(); // não coloque lógica num tratador de eventos, simplesmente invoque algum método de nome legível que contenha sua lógica
}

Método com a lógica do SAIR:

private void sair() {
    int option = JOptionPane.showConfirmDialog(objetoDoSeuFrame, // evite null, passe o objeto da sua tela
                                               "Tem certeza que quer fechar?",
                                               "Fechar",
                                               JOptionPane.OK_CANCEL_OPTION,
                                               JOptionPane.QUESTION_MESSAGE);
    if (option == JOptionPane.OK_OPTION) {
        System.exit(0);
    }
}
1 curtida

Vou enviar todo o código:

package appteste;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

/**
 *
 * @author Helton
 */
public class appteste extends JFrame {
	
	private JLabel labelEsp;
	private JLabel labelEsp2;
	private JLabel labelEsp3;
	private JLabel labelNome;
	private JTextField textNome;
	private JLabel labelIdade;
	private JTextField textIdade;
	private JLabel labelSenha;
	private JPasswordField textSenha;
	private JButton buttonLogin;
	private JRadioButton btnMasc, btnFem;
	private ButtonGroup radGroup;
	private JLabel labelSexo;
	
	public appteste() {
		super("Login");
		
		//Rótulos
		labelEsp   = new JLabel("                                                                                ");
		labelEsp2  = new JLabel("                                                                                   ");
		labelEsp3  = new JLabel("                               ");
		labelNome  = new JLabel("Nome") ;
		labelIdade = new JLabel("Idade");
		labelSenha = new JLabel("Senha");
		labelSexo  = new JLabel("Sexo") ;
		
		//Coloração
		labelNome.setForeground (Color.white);
		labelIdade.setForeground(Color.white);
		labelSenha.setForeground(Color.white);
		labelSexo.setForeground(Color.white) ; 
		
		//Botões Rádio
		btnMasc  = new JRadioButton("Masculino");
		btnFem   = new JRadioButton("Feminino") ;
		radGroup = new ButtonGroup()            ;
		btnMasc.setMnemonic(KeyEvent.VK_1);
		btnFem.setMnemonic(KeyEvent.VK_2) ;
		radGroup.add(btnMasc);
		radGroup.add(btnFem);
		
		//Campos de texto
		textSenha  = new JPasswordField(25);
		textSenha.setEchoChar('*');
		textNome   = new JTextField(25);
		textIdade  = new JTextField(4) ;
		
		//Botões
		buttonLogin  = new JButton("                  ENTRAR                  ")  ;
		
		//Coloração    
		buttonLogin.setBackground(new Color (224, 102, 255));
		buttonLogin.setForeground(Color.white);
		buttonLogin.setAlignmentY(CENTER_ALIGNMENT);
		this.getContentPane().setBackground(new Color(139, 000, 139));
		btnMasc.setBackground(new Color(139, 000, 139));
		btnFem.setBackground (new Color(139, 000, 139));
		btnMasc.setForeground(Color.white);
		btnFem.setForeground (Color.white);
		
		//Capturar painel do JFrame
		Container pane = this.getContentPane();
		JPanel pane2   = new JPanel(new FlowLayout(FlowLayout.CENTER));
		pane2.setBackground(new Color(139, 000, 139));
		
		//Define o tipo de layout
		pane.setLayout(new FlowLayout(FlowLayout.LEFT));
		
		//Inserção
		pane.add(labelNome);
		pane.add(textNome);
		pane.add(labelIdade);
		pane.add(labelEsp2);
		pane.add(textIdade);
		pane.add(labelEsp);
		pane.add(labelSenha);
		pane.add(textSenha);
		pane.add(labelSexo);
		pane.add(btnMasc);
		pane.add(btnFem);
		pane.add(pane2);
		pane2.add(buttonLogin);
		
		this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		this.setSize(310,380);
		this.setResizable(false);
		this.setVisible(true);
		pane2.setVisible(true);
		pane2.setSize(20, 380);

		//Ação
		JFrame.addWindowListener(new java.awt.event.WindowAdapter() {
			public void windowClosing(java.awt.event.WindowEvent e) {
				if(e.getID() == WindowEvent.WINDOW_CLOSING) {
					int selectedOption = JOptionPane.showConfirmDialog(null, "Tem certeza que quer fechar?", "Fechar", 
						JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
					
					if(selectedOption == JOptionPane.OK_OPTION) {
						System.exit(0);
					}
				}
			}
		});
	}
	
	//Adiciona componentes ao painel
	
	/**
     * @param args the command line arguments
     */
	public static void main(String[] args) {
		appteste log = new appteste();
		// TODO code application logic here
	}
}

A sua classe já é o JFrame ao qual você quer adicionar o WindowListener: class appteste extends JFrame
Então é só chamar diretamente o addWindowListener ou então, se achar mais legível, chama this.addWindowListener

1 curtida

Muito obrigado.
No final de tudo foi só tirar o JFrame. e só deixar o addWindowListener.

Ficou assim:

addWindowListener(new java.awt.event.WindowAdapter() {
	public void windowClosing(java.awt.event.WindowEvent e) {
		if(e.getID() == WindowEvent.WINDOW_CLOSING) {
			int selectedOption = JOptionPane.showConfirmDialog(null, "Tem certeza que quer fechar?", "Fechar",
				JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
			
			if(selectedOption == JOptionPane.OK_OPTION) {
				System.exit(0);
			}
		}
	}
});
1 curtida