Search code examples
javaswingjframefocuslistener

FocusListener behavior


I have a JFrame that I want closed when the user clicks off of it. I have two JTextFields and a JButton (username, password, submit). When I give them all the FocusListener, anytime the user goes from one field to another the window closes. How can I allow the user to go from field to field and only close it if the user clicks anywhere OUT of the pop up window?

public class LoginForm {

    static JTextField userName;
    static JTextField password;
    static JButton submit;
    JFrame main;
    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();

    UserSession session;

    public LoginForm(){

        Handler handle = new Handler();  //inner class
        LoginFormFocusListener fl = new LoginFormFocusListener();   //inner class

        main = new JFrame("Please Login");

        main.setUndecorated(true);
        main.setBounds((dim.width/2) - (500/2),(dim.height/2) - (150/2),500,150);
        main.setVisible(true);
        main.setAlwaysOnTop(true);
        main.setResizable(false);
        main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        userName = new JTextField(10);
        password = new JTextField(10);
        main.setLayout(new GridLayout(0,1));

        JPanel panel = new JPanel();
        main.add(panel);
        panel.add(new JLabel("Username: "));
        panel.add(userName);
        panel.add(new JLabel("Password: "));
        panel.add(password);

        submit = new JButton("Submit");
        panel.add(submit);

        userName.addFocusListener(fl);
        password.addFocusListener(fl);
        submit.addFocusListener(fl);

        submit.addActionListener(handle);
    }
}

... (unimportant methods and "Handler" class omitted)

public class LoginFormFocusListener implements FocusListener{

    public void focusGained(FocusEvent fe) {
        System.out.println("focus gained...");
        System.out.println("click off of this window to close...");
    }

    public void focusLost(FocusEvent fe){
    System.out.println("focus lost...");
    WindowEvent winEvt = new WindowEvent(main, 0);
    winEvt.getWindow().dispose();
    }

}



//test
public static void main(String args[]){
    SwingUtilities.invokeLater(new Runnable(){  
        public void run(){  
        new LoginForm();  
    }  
    });  
}

Solution

  • Don't use a FocusListener for this since these are for components that gain and lose the focus, not for top level windows. Perhaps use a WindowListener listening for the window is deactivated or iconified.

    For example:

    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    
    public class WindowListenerFun {
       public static void main(String[] args) {
          JPanel panel = new JPanel();
          panel.add(new JTextField(10));
          panel.add(new JButton("button"));
          JFrame frame = new JFrame("Bad Frame");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.add(panel);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
    
          frame.addWindowListener(new WindowAdapter() {
    
             @Override
             public void windowIconified(WindowEvent wEvt) {
                ((JFrame)wEvt.getSource()).dispose();
             }
    
             @Override
             public void windowDeactivated(WindowEvent wEvt) {
                ((JFrame)wEvt.getSource()).dispose();
             }
    
          });
       }
    }