更改 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;
}
}
我正在更改 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;
}
}