简体   繁体   中英

Focus component after changing content pane of JFrame

I'm changing my JFrame 's content pane and simply want to focus a JTextField in the new panel. So I'm doing this:

JPanel pNew = new JPanel();
frame.setContentPane(pNew);
frame.revalidate();
frame.repaint();

public JPanel() {
    ...
    tf.requestFocusInWindow();
}

When I use setVisible(false) and setVisible(true) instead of revalidating and repainting my frame, I get my wished effect, but that's not the way I want to do it.

What else happens in setVisible() but revalidating and repainting?

A CardLayout is typically used to swap panels.

However, even the default implementation of CardLayout does not set focus on the panel when it is swapped. However you can check out Card Layout Focus which will allow you to request focus on the panel when it is switched.

The requestFocusInWindow() method only works on a component that is displayed in a visible frame. So you can't invoke the method in the constructor of the class.

You could use the RequestFocsListener found in Dialog Focus . It will wait until the panel is added to a visible GUI before generating the event.

I got it to work simply by putting the requestFocusInWindow() call in the button's action listener. As camickr mentioned the call needs to be made after the constructor. Here's an example program showing how I got it to work. Hope it helps!

public class PanelRevalidate {
    public JFrame frame;
    public MyPanel panel1, panel2;

    public PanelRevalidate() {
        frame = new JFrame();
        panel1 = new MyPanel(1);
        panel2 = new MyPanel(2);
        frame.setContentPane(panel1);

        panel1.getSwap().addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                frame.setContentPane(panel2);
                frame.revalidate();
                panel2.getTextField().requestFocusInWindow();
            }
        });

        panel2.getSwap().addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                frame.setContentPane(panel1);
                frame.revalidate();
                panel1.getTextField().requestFocusInWindow();
            }
        });

        frame.setVisible(true);
        frame.setResizable(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                new PanelRevalidate();
            }
        });
    }

}

And the MyPanel class:

public class MyPanel extends JPanel {

    public JTextField tf;
    public JButton swap;
    public JLabel panel_label;

    public MyPanel(int n) {
        tf = new JTextField(25);
        swap = new JButton("Swap");
        panel_label = new JLabel("panel " + n);

        add(tf);
        add(swap);
        add(panel_label);
    }

    public JButton getSwap() {
        return swap;
    }

    public JTextField getTextField() {
        return tf;
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM