【问题标题】:How to request focus on JComponent after changing JPanel in JFrame在 JFrame 中更改 JPanel 后如何请求对 JComponent 的关注
【发布时间】:2018-06-17 17:59:21
【问题描述】:

我有这两个类:

类测试:

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 内发生变化:How can I change the JPanel from another Class?

但是,在将 panel1 更改为 panel2 之后,我现在如何将焦点设置在 JTextField 上?

我尝试将grabFocus(); 添加到JTextField,但它不起作用,requestFocus(); 也不起作用。

提前致谢!

【问题讨论】:

    标签: java swing jpanel focus jtextfield


    【解决方案1】:
    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();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-16
      • 2021-12-23
      • 2011-03-30
      • 2010-12-26
      • 1970-01-01
      • 2010-09-18
      • 1970-01-01
      相关资源
      最近更新 更多