Вопрос

Я использую несколько 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 внутри прослушивателя фокуса, чтобы назначить текущий объект, но не уверен, как сделать это «безопасным» (например,их нужно синхронизировать?).

Может быть, мне чего-то не хватает?

Это было полезно?

Решение

Вам нужно использовать 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);

Другие советы

На самом деле это происходит в 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".Это усложняет задачу, поскольку изменяется длина строки.

Я думаю, что решение 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);
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top