I have these two classes:
class Test:
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);
});
}
}
class Panels:
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);
}
};
}
And as you can see, the JPanel changes inside the JFrame
, after clicking the JButton
: How can I change the JPanel from another Class?
But how can I now set the focus on the JTextField
, after changing panel1 to panel2?
I've tried to add grabFocus();
to the JTextField
, but it didn't work and requestFocus();
didn't work as well.
Thanks in advance!
showView(...)
with invokeLater. Your ActionListener is being called on the EDT, so this is unnecessary code.requestFocusInWindow()
on it after making it visible, and it should have focus. For example:
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();
}
}
});
Myself, I would use CardLayout to do my swapping and would not use the kludge of getting components via getComponents()
but rather using much less brittle method calls.
For example:
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();
}
}