自动将焦点设置在JTextField上

时间:2013-12-01 08:22:48

标签: java swing jframe jtextfield caret

无法找到答案(或者很可能我没有正确询问)。

我的JTextField textfield1启动后,如何将注意力集中在JFrame上? 通过焦点我的意思是用户可以立即开始输入,而无需点击JTextField

我尝试textfield1.setCaretPosition(0)textfield1.moveCaretPosition(0),但都没有效果。

点击后,焦点仍然停留在提交按钮上(即使我在点击后调用上面的2)。

2 个答案:

答案 0 :(得分:4)

在Swing中可以通过多种方式控制焦点,但在您的情况下,最简单的可能就是使用JTextField#requestFocusInWindow

这有点偏离主题,但你可能想看看How to use the a Focus Subsystem

答案 1 :(得分:3)

比直接请求关注初始组件更有趣的是自定义FocusTraversalPolicy,它实现了查找/配置默认值的一般机制。基本概念已在其api中可用,具有返回初始/ defaultComponent的方法,f.i。:

  

public abstract Component getDefaultComponent(Container aContainer)

     

返回要关注的默认Component。这个组件将是   首先在遍历新的焦点遍历时获得焦点   以aContainer为基础的循环。

默认实现返回循环中的第一个组件,自定义实现可能会查找自定义指示符f.i.客户财产。简单的用法会将该策略设置为在其contentPane中具有标记的框架,如:

// 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它没有捕获,但是:

  • 框架的默认策略在其实例化时在内部设置 - 因此,在创建框架
  • 之前必须配置keyboardEocusManager 并不奇怪。
  • 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);
    }
}