JFormattedTextField 焦点上的插入符位置

发布于 2024-08-20 10:59:24 字数 891 浏览 13 评论 0原文

我在程序中使用了一些 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) {}

    });

我尝试了很多方法来让他工作。我尝试过使用final关键字,它有效,但仅适用于单个文本字段。

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

也许我缺少什么?

I am utilizing a few JFormattedTextFields in my program. For some reason when the text field gains focus after a click on the text field, the caret position always jumps to the left (position 0). I would like the caret to end up at the location clicked by the user. So if I click in between two digits, the caret should end up in between those two digits.

So I implemented a FocusListener that would get the click location and set the caret position there.

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) {}

    });

I've tried a number of things to get his to work. I've tried using the final keyword, which works, but only for a single textfield.

I've used set/get methods inside the focus listener to assign the current object, but am not sure about how to make this "safe" (e.g. do they need to be synchronized?).

Maybe there is something I am missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

守护在此方 2024-08-27 10:59:24

您需要使用鼠标监听器:

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);

You need to use a 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);
蓝海似她心 2024-08-27 10:59:24

这实际上发生在 AbstractFormatter.install(JFormattedTextField) 中,当字段获得焦点时调用它。

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

示例(假设字段值是 int< /code>):

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());
    }
}

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

This actually happens in AbstractFormatter.install(JFormattedTextField), which is called when the field gains focus.

I'm not sure why it is designed this way, but you can override this behaviour (as long as your formatter does not change the length of the string in the field.)

Example (assuming the field value is an 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());
    }
}

Note that this is not the same as the default Integer formatter. The default formatter uses a DecimalFormat that separates groups of digits, e.g. "1,000,000". This makes the task harder as it changes the length of the string.

你的他你的她 2024-08-27 10:59:24

我认为对 finnw 的解决方案进行了一些改进。例子:

public static void main(String[] args) {
    NumberFormat format = NumberFormat.getInstance();
    NumberFormatter formatter = new NumberFormatter(format) {
        @Override
        public void install(JFormattedTextField pField) {
            final JFormattedTextField oldField = getFormattedTextField();
            final int oldLength = pField.getDocument().getLength();
            final int oldPosition = pField.getCaretPosition();

            super.install(pField);

            if (oldField == pField && oldLength == pField.getDocument().getLength()) {
                pField.setCaretPosition(oldPosition);
            }
        }
    };
    JFormattedTextField field = new JFormattedTextField(formatter);
    field.setValue(1234567890);

    JOptionPane.showMessageDialog(null, field);
}

Improved on finnw's solution a bit I think. Example:

public static void main(String[] args) {
    NumberFormat format = NumberFormat.getInstance();
    NumberFormatter formatter = new NumberFormatter(format) {
        @Override
        public void install(JFormattedTextField pField) {
            final JFormattedTextField oldField = getFormattedTextField();
            final int oldLength = pField.getDocument().getLength();
            final int oldPosition = pField.getCaretPosition();

            super.install(pField);

            if (oldField == pField && oldLength == pField.getDocument().getLength()) {
                pField.setCaretPosition(oldPosition);
            }
        }
    };
    JFormattedTextField field = new JFormattedTextField(formatter);
    field.setValue(1234567890);

    JOptionPane.showMessageDialog(null, field);
}
云淡月浅 2024-08-27 10:59:24

如果您不能或不想覆盖格式化程序:

    import java.awt.event.FocusEvent;
    import java.awt.event.FocusListener;
    import java.text.NumberFormat;
    
    import javax.swing.JFormattedTextField;
    import javax.swing.JOptionPane;
    import javax.swing.SwingUtilities;
    import javax.swing.text.NumberFormatter;
    
    public class TestJFormattedTextFieldFocus {
    
        public static void main(String[] args) {
            NumberFormat format = NumberFormat.getInstance();
            NumberFormatter formatter = new NumberFormatter(format);
            JFormattedTextField field = new JFormattedTextField(formatter);
            field.addFocusListener(new FocusListener() {
    
                @Override
                public void focusLost(FocusEvent e) {
                }
    
                @Override
                public void focusGained(FocusEvent e) {
                    restoreCaretPosition();
                }
    
                private void restoreCaretPosition() {
                    int caretPosition = field.getCaretPosition();
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            field.setCaretPosition(caretPosition);
                        }
                    });
                }
            });
            field.setValue(1234567890);
            JOptionPane.showMessageDialog(null, field);
        }
    
    }

If you cannot or do not want to override the Formatter:

    import java.awt.event.FocusEvent;
    import java.awt.event.FocusListener;
    import java.text.NumberFormat;
    
    import javax.swing.JFormattedTextField;
    import javax.swing.JOptionPane;
    import javax.swing.SwingUtilities;
    import javax.swing.text.NumberFormatter;
    
    public class TestJFormattedTextFieldFocus {
    
        public static void main(String[] args) {
            NumberFormat format = NumberFormat.getInstance();
            NumberFormatter formatter = new NumberFormatter(format);
            JFormattedTextField field = new JFormattedTextField(formatter);
            field.addFocusListener(new FocusListener() {
    
                @Override
                public void focusLost(FocusEvent e) {
                }
    
                @Override
                public void focusGained(FocusEvent e) {
                    restoreCaretPosition();
                }
    
                private void restoreCaretPosition() {
                    int caretPosition = field.getCaretPosition();
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            field.setCaretPosition(caretPosition);
                        }
                    });
                }
            });
            field.setValue(1234567890);
            JOptionPane.showMessageDialog(null, field);
        }
    
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文