简体   繁体   English

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

[英]How to request focus on JComponent after changing JPanel in JFrame

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? 如您所见,单击JButton后,JPanel在JFrame内发生了变化: 如何从另一个类更改JPanel?

But how can I now set the focus on the JTextField , after changing panel1 to panel2 ? 但是,在将panel1更改为panel2之后,现在如何在JTextField上设置焦点?

I've tried to add grabFocus(); 我试图添加grabFocus(); to the JTextField , but it didn't work and requestFocus(); JTextField ,但是它不起作用并且requestFocus(); didn't work as well. 效果不佳。

Thanks in advance! 提前致谢!

  1. There's no need to call showView(...) with invokeLater. 无需使用invokeLater调用showView(...) Your ActionListener is being called on the EDT, so this is unnecessary code. 您的ActionListener在EDT上被调用,因此这是不必要的代码。
  2. If you had a handle to the JTextField, you could call requestFocusInWindow() on it after making it visible, and it should have focus. 如果您具有JTextField的句柄,则可以在使其可见后对其调用requestFocusInWindow() ,并且它应该具有焦点。

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. 我自己,我将使用CardLayout进行交换,并且不会使用通过getComponents()获取组件的麻烦,而是会使用不那么脆弱的方法调用。

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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM