JFormattedTextField在焦点上的插入位置

Sha*_*arb 7 java swing focus caret jformattedtextfield

我在我的程序中使用了一些JFormattedTextFields.由于某些原因,当单击文本字段后文本字段获得焦点时,插入符号位置始终跳转到左侧(位置0).我希望插入符号最终位于用户点击的位置.因此,如果我在两个数字之间点击,则插入符应该在这两个数字之间.

所以我实现了一个FocusListener,它将获得点击位置并在那里设置插入位置.

FocusListener focusListener = new FocusListener(){


    public void focusGained(FocusEvent evt) {

        JFormettedTextField jftf = (JFormattedTextField) evt.getSource();

        //This is where the caret needs to be.
        int dot = jftf.getCaret().getDot(); 

        SwingUtilities.invokeLater( new Runnable() {

        public void run() {
'the textField that has focus'.setCaretPosition('Some how get the evt or dot');              
              }
           });
        }

    public void focusLost (FocusEvent evt) {}

    });
Run Code Online (Sandbox Code Playgroud)

我尝试了很多让他上班的事情.我尝试过使用final关键字,但是只能用于单个文本字段.

我在焦点监听器中使用了set/get方法来分配当前对象,但我不确定如何使其"安全"(例如,它们是否需要同步?).

也许有一些我想念的东西?

cam*_*ckr 12

您需要使用MouseListener:

MouseListener ml = new MouseAdapter()
{
    public void mousePressed(final MouseEvent e)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                JTextField tf = (JTextField)e.getSource();
                int offset = tf.viewToModel(e.getPoint());
                tf.setCaretPosition(offset);
            }
        });
    }
};

formattedTextField.addMouseListener(ml);
Run Code Online (Sandbox Code Playgroud)

  • @Sanoj,`invokeLater`引入的延迟是它工作所必需的.通常,当单击该字段时,它会获得焦点,这会使格式化程序重新格式化值并更新字段文本.这样的副作用是插入符号.使用`invokeLater`,这个`run()`方法在焦点事件处理完成之前不会执行,因此您知道一旦将插入符号放在正确的位置它就会保留在那里. (2认同)

fin*_*nnw 7

这实际上发生在AbstractFormatter.install(JFormattedTextField),当场获得焦点时调用.

我不确定为什么它是这样设计的,但你可以覆盖这种行为(只要你的格式化程序不改变字段中字符串的长度.)

示例(假设字段值为a int):

class IntFormatter extends AbstractFormatter {
    @Override
    public void install(final JFormattedTextField ftf) {
        int prevLen = ftf.getDocument().getLength();
        int savedCaretPos = ftf.getCaretPosition();
        super.install(ftf);
        if (ftf.getDocument().getLength() == prevLen) {
            ftf.setCaretPosition(savedCaretPos);
        }
    }

    public Object stringToValue(String text) throws ParseException {
        return Integer.parseInt(text);
    }

    public String valueToString(Object value) throws ParseException {
        return Integer.toString(((Number) value).intValue());
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这与默认Integer格式化程序不同.默认格式化程序使用DecimalFormat分隔数字组,例如"1,000,000".这使得任务变得更难,因为它改变了字符串的长度.