如何在 JFrame 中更改 JPanel 后请求关注 JComponent



我有两个类:

班级测试:

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();也没有那么好用。

提前感谢!

  1. 无需使用 invokeLater 调用showView(...)。您的 ActionListener 正在 EDT 上被调用,因此这是不必要的代码。
  2. 如果你有 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();
    }
}

最新更新