默认情况下,NimbusLookAndFeel
中的 JFileChooser
不会将焦点显示在用户键入文件路径的 JTextField
上。 JFileChooser
中的焦点所有者是 JComboBox
,如图所示。
现在,当用户打开 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/