更改 JFrame 的内容窗格后的焦点组件

Focus component after changing content pane of JFrame

我正在更改 JFrame 的内容窗格,只想在新面板中聚焦 JTextField。所以我这样做:

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

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

当我使用 setVisible(false)setVisible(true) 而不是重新验证和重新绘制我的框架时,我得到了我想要的效果,但这不是我想要的方式。

setVisible() 除了重新验证和重绘之外还会发生什么?

A CardLayout 通常用于交换面板。

然而,即使是 CardLayout 的默认实现也不会在切换面板时将焦点设置在面板上。但是,您可以查看 Card Layout Focus,这将允许您在面板切换时请求将焦点放在面板上。

requestFocusInWindow() 方法仅适用于显示在可见框架中的组件。所以你不能调用class的构造函数中的方法。

您可以使用 Dialog Focus 中的 RequestFocsListener。它将等到面板被添加到可见的 GUI 之后才会生成事件。

我只需将 requestFocusInWindow() 调用放入按钮的动作侦听器中即可使其正常工作。正如 camickr 提到的,调用需要在构造函数之后进行。这是一个示例程序,展示了我是如何让它工作的。希望对您有所帮助!

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

}

还有我的面板 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;
    }

}