我有两个类:
班级测试:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
//frame
private static JFrame frame = new JFrame() {
private static final long serialVersionUID = 1L;
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 200);
setLocationRelativeTo(null);
setLayout(new BorderLayout());
viewPanel = new JPanel(new BorderLayout());
add(viewPanel);
}
};
private static JPanel viewPanel;
//change the panels
public static void showView(JPanel panel) {
viewPanel.removeAll();
viewPanel.add(panel, BorderLayout.CENTER);
viewPanel.revalidate();
viewPanel.repaint();
}
//main method
public static void main (String [] args) {
SwingUtilities.invokeLater(() -> showView(Panels.panel1));
SwingUtilities.invokeLater(() -> {
frame.setVisible(true);
});
}
}
类面板:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
//panels
public class Panels {
//first panel
static JPanel panel1 = new JPanel() {
private static final long serialVersionUID = 1L;
{
JButton button = new JButton("Click here!");
add(button);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
SwingUtilities.invokeLater(() -> Test.showView(panel2));
}
});
}
};
//second panel
static JPanel panel2 = new JPanel() {
private static final long serialVersionUID = 1L;
{
JTextField textField = new JTextField(5);
add(textField);
}
};
}
如您所见,单击JButton
后,JPanel 在JFrame
内发生了变化:如何从另一个类更改 JPanel?
但是,在将 panel1 更改为 panel2 之后,我现在如何将焦点设置在JTextField
上?
我试图将grabFocus();
添加到JTextField
中,但它不起作用,requestFocus();
也没有那么好用。
提前感谢!
- 无需使用 invokeLater 调用
showView(...)
。您的 ActionListener 正在 EDT 上被调用,因此这是不必要的代码。 - 如果你有 JTextField 的句柄,你可以在它可见后调用它
requestFocusInWindow()
,它应该有焦点。
例如:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// SwingUtilities.invokeLater(() -> Test.showView(panel2)); // not needed
Test.showView(panel2);
Component[] comps = panel2.getComponents();
if (comps.length > 0) {
comps[0].requestFocusInWindow();
}
}
});
我自己,我会使用 CardLayout 进行交换,并且不会使用通过getComponents()
获取组件的麻烦,而是使用不那么脆弱的方法调用。
例如:
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class MyPanelTest extends JPanel {
private TextFieldPanel textFieldPanel = new TextFieldPanel();
private CardLayout cardLayout = new CardLayout();
public MyPanelTest() {
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton(new ButtonAction("Press Me")));
setPreferredSize(new Dimension(400, 200));
setLayout(cardLayout);
add(buttonPanel, "button panel");
add(textFieldPanel, TextFieldPanel.NAME);
}
private class ButtonAction extends AbstractAction {
public ButtonAction(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent e) {
cardLayout.show(MyPanelTest.this, TextFieldPanel.NAME);
textFieldPanel.textFieldRequestFocus();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("My Panel Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyPanelTest());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
@SuppressWarnings("serial")
class TextFieldPanel extends JPanel {
public static final String NAME = "TEXT_FIELD_PANEL";
private JTextField textField = new JTextField(10);
public TextFieldPanel() {
add(textField);
}
public void textFieldRequestFocus() {
textField.requestFocusInWindow();
}
}