Java 当JFormattedTextField获得焦点时,如何选择其中的所有文本?

Java 当JFormattedTextField获得焦点时,如何选择其中的所有文本?,java,user-interface,swing,Java,User Interface,Swing,我有一个使用Swing的小型Java桌面应用程序。有一个数据输入对话框,其中包含一些不同类型的输入字段(JTextField、JComboBox、JSpinner、JFormattedTextField)。当我通过在表单中使用Tab键或鼠标单击来激活JFormattedTextFields时,我希望它选择当前包含的所有文本。这样,用户就可以开始键入并覆盖默认值 我该怎么做?我确实使用了一个FocusListener/FocusAdapter,它在JFormattedTextField上调用sel

我有一个使用Swing的小型Java桌面应用程序。有一个数据输入对话框,其中包含一些不同类型的输入字段(JTextField、JComboBox、JSpinner、JFormattedTextField)。当我通过在表单中使用Tab键或鼠标单击来激活JFormattedTextFields时,我希望它选择当前包含的所有文本。这样,用户就可以开始键入并覆盖默认值

我该怎么做?我确实使用了一个FocusListener/FocusAdapter,它在JFormattedTextField上调用selectAll(),但它没有选择任何内容,尽管调用了FocusAdapter的FocusGaund()方法(请参见下面的代码示例)


有什么想法吗?有趣的是,选择所有文本显然是JTextField和JSpinner的默认行为,至少在切换表单时是这样。

使用SwingUtilities.invokeLater包装调用,以便在处理所有挂起的AWT事件后发生:

pricePerLiter.addFocusListener(new java.awt.event.FocusAdapter() {
    public void focusGained(java.awt.event.FocusEvent evt) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                pricePerLiter.selectAll();
            }
        });
    }
});

这是因为JFormattedTextfield覆盖processFocusEvent,以便在获得焦点/丢失焦点时格式化

一种可靠的方法是扩展JFormattedTextField并重写processFocusEvent方法:

new JFormattedTextField("...") {  
        protected void processFocusEvent(FocusEvent e) {  
            super.processFocusEvent(e);  
            if (e.isTemporary())  
                return;  
            SwingUtilities.invokeLater(new Runnable() {  
                @Override  
                public void run() {  
                    selectAll();  
                }   
            });  
        }  
    };

使用focusListener可能并不总是有效。因为这取决于相对于processFocusEvent调用focusListener的时间。

除上述内容外,如果您希望所有文本字段都使用focusListener,可以执行以下操作:

KeyboardFocusManager.getCurrentKeyboardFocusManager()
    .addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener()
{
    public void propertyChange(final PropertyChangeEvent e)
    {
        if (e.getNewValue() instanceof JTextField)
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    JTextField textField = (JTextField)e.getNewValue();
                    textField.selectAll();
                }
            });

        }
    }
});

camickr的代码可以稍微改进。当焦点从JTextField传递到另一种组件(如按钮)时,最后一个自动选择不会被清除。可以通过以下方式进行修复:

    KeyboardFocusManager.getCurrentKeyboardFocusManager()
        .addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener()
    {
        @Override
        public void propertyChange(final PropertyChangeEvent e)
        {

            if (e.getOldValue() instanceof JTextField)
            {
                    SwingUtilities.invokeLater(new Runnable()
                    {
                            @Override
                            public void run()
                            {
                                    JTextField oldTextField = (JTextField)e.getOldValue();
                                    oldTextField.setSelectionStart(0);
                                    oldTextField.setSelectionEnd(0);
                            }
                    });

            }

            if (e.getNewValue() instanceof JTextField)
            {
                    SwingUtilities.invokeLater(new Runnable()
                    {
                            @Override
                            public void run()
                            {
                                    JTextField textField = (JTextField)e.getNewValue();
                                    textField.selectAll();
                            }
                    });

            }
        }
    });

我知道这有点过时,但我提出了一个更干净的解决方案,没有调用器:

private class SelectAllOfFocus extends FocusAdapter {

    @Override
    public void focusGained(FocusEvent e) {
        if (! e.isTemporary()) {
            JFormattedTextField textField = (JFormattedTextField)e.getComponent();
            // This is needed to put the text field in edited mode, so that its processFocusEvent doesn't
            // do anything. Otherwise, it calls setValue, and the selection is lost.
            textField.setText(textField.getText());
            textField.selectAll();
        }
    }

}

谢谢,就这样。我只能猜测NumberFormatter正在做一些撤销selectAll()的事情?+1需要这个,我自己也记不起怎么做了,谷歌搜索并立即找到了答案。谢谢当您已经在EDT线程上时,为什么要使用invokeLater执行它?因为
invokeLater
确保所有挂起的AWT事件都已处理。我不喜欢此代码,因为它修改组件内部状态,只是为了获得选择?
private class SelectAllOfFocus extends FocusAdapter {

    @Override
    public void focusGained(FocusEvent e) {
        if (! e.isTemporary()) {
            JFormattedTextField textField = (JFormattedTextField)e.getComponent();
            // This is needed to put the text field in edited mode, so that its processFocusEvent doesn't
            // do anything. Otherwise, it calls setValue, and the selection is lost.
            textField.setText(textField.getText());
            textField.selectAll();
        }
    }

}