自动将焦点设置在JTextField上

4
无法找到答案(或者说我可能没有恰当地提问)。
如何在我的JFrame启动时立即将焦点设置在JTextField textfield1上? 所谓的焦点是指用户可以立即开始输入而不必单击JTextField。
我尝试了textfield1.setCaretPosition(0)和textfield1.moveCaretPosition(0),但都没有起作用。
此外,在单击提交按钮后,焦点仍然留在提交按钮上(即使在调用上述两个方法之后)。

2
请参见JComponent.requestFocusInWindow() - Andrew Thompson
2
你尝试过 textField1.requestFocusInWindow(); 吗? - paulsm4
谢谢,我尝试在谷歌上搜索,但是没有想到“focus”是正确的词。 - Cody
2个回答

5

1
当我的JFrame被初始化时,是否应该包装成invokeLater? - mKorbel

4
比直接请求初始组件的焦点更有趣的是使用自定义的FocusTraversalPolicy实现通用机制来查找/配置默认值。它的api中已经有了基本概念,包括返回初始/默认组件的方法,例如:
```java public abstract Component getDefaultComponent(Container aContainer) ```
返回要聚焦的默认组件。当进入以aContainer为根的新焦点遍历周期时,该组件将是第一个接收焦点的组件。
默认实现返回循环中的第一个组件,自定义实现可能会查找自定义指示器,例如客户端属性。简单的用法是将该策略设置为具有内容窗格中标记的框架,类似于:
```java frame.setFocusTraversalPolicyProvider(true); frame.setFocusTraversalPolicy(new MyCustomPolicy()); ```
// a custom policy checking for the property
FocusTraversalPolicy policy = new LayoutFocusTraversalPolicy() {

    @Override
    public Component getDefaultComponent(Container aContainer) {
        if (aContainer instanceof JComponent) {
            JComponent parent = (JComponent) aContainer;
            if (parent.getClientProperty("defaultFocus") instanceof Component) {
                return (Component) parent.getClientProperty("defaultFocus");
            }
        }
        if (aContainer instanceof RootPaneContainer) {
            RootPaneContainer root = (RootPaneContainer) aContainer;
            JComponent parent = (JComponent) root.getContentPane();
            if (parent.getClientProperty("defaultFocus") instanceof Component) {
                return (Component) parent.getClientProperty("defaultFocus");
            }

        }
        return super.getDefaultComponent(aContainer);
    }

};
JFrame frame = ... // create  and fill
JTextField field = new JTextField(20);
frame.add(field, BorderLayout.SOUTH);
// set the client property 
((JComponent) frame.getContentPane()).putClientProperty("defaultFocus", field);
// set the custom policy
frame.setFocusTraversalPolicy(policy);

更加优雅的方法是默认使用此策略 - 可以通过将其安装为KeyboardFocusManager的默认策略来实现。有了这个,使用将会变得更简单:

  • 在应用程序生命周期的早期安装自定义默认值
  • 标记初始焦点组件(无需手动设置框架策略)

代码:

// very early in the application code
initializeDefaultFocusTraversalPolicy();

// default in any frame
JFrame frame = ... // create  and fill
JTextField field = new JTextField(20);
frame.add(field, BorderLayout.SOUTH);
// set the client property 
((JComponent) frame.getContentPane())
    .putClientProperty(DelegatingFocusTraversalPolicy.DEFAULT_FOCUS_KEY, field);

如果没有一个小技巧,Swing就不会是Swing:

  • 窗口的默认策略在创建时就被内部设置了 - 因此键盘焦点管理器必须在创建框架之前进行配置
  • UIManager对于管理器的默认设置有自己的想法,事实上,在创建非常第一个框架时无条件地配置它(这将覆盖我们自己的默认设置)

解决方法是创建一个虚拟框架,然后设置策略:

public static void initializeDefaultFocusTraversalPolicy() {
    // a custom default policy is overwritten by the UIManager the
    // very first time it sees a top-level container created
    // it does so  unconditionally depending on a flag in LAFState
    // see UIManager.maybeInitializeFocusPolicy
    // so we tricks him into doing it for a fake frame
    new JFrame();
    // and set our custom default afterwards
    FocusTraversalPolicy p = KeyboardFocusManager.getCurrentKeyboardFocusManager()
         .getDefaultFocusTraversalPolicy();
    KeyboardFocusManager.getCurrentKeyboardFocusManager()
         .setDefaultFocusTraversalPolicy(new CustomFocusTraversalPolicy(p));
}

/**
 * Basically the same custom policy as the ad-hoc above, just with
 * delegating 
 */
public static class CustomFocusTraversalPolicy extends FocusTraversalPolicy {
    public static final String DEFAULT_FOCUS_KEY = "defaultFocus";
    private FocusTraversalPolicy delegate;

    public CustomFocusTraversalPolicy(FocusTraversalPolicy delegate) {
        this.delegate = Contract.asNotNull(delegate, "the delegate must not be null");
    }

    @Override
    public Component getDefaultComponent(Container container) {
        if (container instanceof JComponent) {
            JComponent parent = (JComponent) container;
            if (parent.getClientProperty(DEFAULT_FOCUS_KEY) instanceof Component) {
                return (Component) parent.getClientProperty(DEFAULT_FOCUS_KEY);
            }
        }
        if (container instanceof RootPaneContainer) {
            RootPaneContainer root = (RootPaneContainer) container;
            JComponent parent = (JComponent) root.getContentPane();
            if (parent.getClientProperty(DEFAULT_FOCUS_KEY) instanceof Component) {
                return (Component) parent.getClientProperty(DEFAULT_FOCUS_KEY);
            }

        }
        return delegate.getDefaultComponent(container);
    }
    @Override
    public Component getComponentAfter(Container aContainer,
            Component aComponent) {
        return delegate.getComponentAfter(aContainer, aComponent);
    }

    @Override
    public Component getComponentBefore(Container aContainer,
            Component aComponent) {
        return delegate.getComponentBefore(aContainer, aComponent);
    }

    @Override
    public Component getFirstComponent(Container aContainer) {
        return delegate.getFirstComponent(aContainer);
    }

    @Override
    public Component getLastComponent(Container aContainer) {
        return delegate.getLastComponent(aContainer);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接