在JFileChooser(NimbusLookAndFeel)中获得JTextField的焦点

时间:2013-07-15 10:01:22

标签: java swing jfilechooser nimbus

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

Screenshot of the JFileChooser (NimbusLookAndFeel)

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

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

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

1 个答案:

答案 0 :(得分:3)

这里的事情是在grabFocusForTextField()调用JTextField不是可显示,因此您无法获得JTextField的焦点。要使组件获得焦点,组件必须首先存在,可见并且可显示,启用和可聚焦。有关详情,请参阅Focus subsystem in docs

您必须在HierarchyListener上注册自己的JFileChooser才能收听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()