JFormattedTextField позиция каретки в фокусе - PullRequest
7 голосов
/ 04 февраля 2010

Я использую несколько 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) {}

    });

Я пробовал несколько вещей, чтобы заставить его работать. Я попытался использовать последнее ключевое слово, которое работает, но только для одного текстового поля.

Я использовал методы set / get внутри слушателя фокуса для назначения текущего объекта, но не уверен, как сделать это «безопасным» (например, нужно ли их синхронизировать?).

Может быть, я что-то упускаю?

Ответы [ 3 ]

10 голосов
/ 04 февраля 2010

Вам необходимо использовать 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);
7 голосов
/ 04 февраля 2010

Это на самом деле происходит в AbstractFormatter.install(JFormattedTextField), который вызывается, когда поле получает фокус.

Я не уверен, почему он разработан таким образом, но вы можете переопределить это поведение (если ваш форматтер не изменяет длину строки в поле.)

Пример (при условии, что значением поля является 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());
    }
}

Обратите внимание, что это не то же самое, что форматер Integer по умолчанию. Форматировщик по умолчанию использует DecimalFormat, который разделяет группы цифр, например, "1,000,000". Это усложняет задачу, так как меняет длину строки.

1 голос
/ 03 июля 2013

Я думаю, что улучшил решение 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);
}
...