java - 在 JFileChooser (NimbusLookAndFeel) 中获取 JTextField 的焦点

标签 java swing jfilechooser nimbus

默认情况下,NimbusLookAndFeel 中的 JFileChooser 不会将焦点显示在用户键入文件路径的 JTextField 上。 JFileChooser 中的焦点所有者是 JComboBox,如图所示。

Screenshot of the JFileChooser (NimbusLookAndFeel)

现在,当用户打开 JFileChooser 时,我如何才能获得 JTextField 的焦点。我尝试通过递归逻辑从 JFileChooser 获取它,从而在 JTextField 上执行 requestFocusInWindow()。这是我完成的完整代码。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class GetFocusForJTextField extends JFrame
{
JButton jb;
JFileChooser jf;

    public GetFocusForJTextField()
    {
        createAndShowGUI();
    }

    private void createAndShowGUI()
    {
        // For NimbusLookAndFeel, JTextField is not
        // the default focus owner in JFileChooser
        try
        {
            UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
        }catch(Exception e){}

        setTitle("Get Focus for JTextField");
        setLayout(new FlowLayout());
        setSize(400,400);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        jb=new JButton("Open JFileChooser");
        jb.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ae)
            {
                showDialog();
            }
        });

        jf=new JFileChooser();

        add(jb);
    }

    // Loop to find the JTextField, the first
    // JTextField in JFileChooser
    private void grabFocusForTextField(Component[] c)
    {
        for(Component k:c)
        {
            if(k instanceof JTextField)
            {
                JTextField jt=(JTextField)k;
                jt.requestFocusInWindow();
                break;
            }
            else if(k instanceof JPanel)
            {
                JPanel jp=(JPanel)k;
                grabFocusForTextField(jp.getComponents());
            }
        }
    }

    private void showDialog()
    {
        jf.showOpenDialog(this);
        grabFocusForTextField(jf.getComponents());
    }

    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable(){
            public void run()
            {
                new GetFocusForJTextField();
            }
        });
    }
}

我仍然无法获得焦点。为什么我没有得到这个。

最佳答案

这里的事情是在调用 grabFocusForTextField()JTextField 不是 displayable 因此您无法获得焦点JTextField。对于要获得焦点的组件,组件必须首先存在、可见且可显示、启用且可聚焦。查看Focus subsystem in docs了解更多。

您必须在 JFileChooser 上注册您自己的 HierarchyListener 以收听 HierarchyEvent。在 NimbusLookAndFeel 中,这可能没有正确完成,或者 JComboBox 被选为焦点所有者。每当组件可显示时,每当 JFileChooser 的层次结构发生更改时,都会触发此事件,并且此时 JTextField 是可显示的。

我已经重写了代码以使其工作。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class GetFocusForJTextField extends JFrame
{
JButton jb;
JFileChooser jf;

    public GetFocusForJTextField()
    {
        createAndShowGUI();
    }

    private void createAndShowGUI()
    {
        // For NimbusLookAndFeel, JTextField is not
        // the default focus owner in JFileChooser
        try
        {
            UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
        }catch(Exception e){}

        setTitle("Get Focus for JTextField");
        setLayout(new FlowLayout());
        setSize(400,400);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        jb=new JButton("Open JFileChooser");
        jb.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ae)
            {
                showDialog();
            }
        });

        jf=new JFileChooser();

        // Even if you add some other JTextField
        // as accessory to JFileChooser
        jf.setAccessory(new JTextField(20));

        jf.addHierarchyListener(new HierarchyListener(){
            public void hierarchyChanged(HierarchyEvent he)
            {
                grabFocusForTextField(jf.getComponents());
            }
        });     

        add(jb);
    }

    // Loop to find the JTextField, the first
    // JTextField in JFileChooser
    // Even if you setAccessory which contains a JTextField
    // or which is JTextField itself, it will not get focus
    private void grabFocusForTextField(Component[] c)
    {
        for(Component k:c)
        {
            if(k instanceof JTextField)
            {
                JTextField jt=(JTextField)k;
                jt.grabFocus();
                break;
            }
            else if(k instanceof JPanel)
            {
                JPanel jp=(JPanel)k;
                grabFocusForTextField(jp.getComponents());
            }
        }
    }

    private void showDialog()
    {
        jf.showOpenDialog(this);
    }

    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable(){
            public void run()
            {
                new GetFocusForJTextField();
            }
        });
    }
}

您还可以使用 requestFocusInWindow() 代替 grabFocus()

关于java - 在 JFileChooser (NimbusLookAndFeel) 中获取 JTextField 的焦点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17651554/

相关文章:

Java JFrame 添加带字段的浏览按钮

java - 如何更改 JFileChooser 中的文本?

java - 我的代码线程已经安全了吗

java - BigDecimal,精度和规模

java - 如何将 String 转换为 java 中的现有标识符?

java - 无法更新子 JFrame 中的结果表

java - 如何解决回文中的 java.lang.NumberFormatException?

java - 没有父信息的节点到字符串

Java Swing BorderLayout resize困难