Как установить положение курсора в конце JFormattedTextField, когда он щелкнут/сфокусирован?

У меня есть кадр с JFormattedTextField(s). Мой упрощенный код может выглядеть так:

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(100,100);
frame.setLayout(new GridLayout(2,2));

JFormattedTextField field1 = new JFormattedTextField(NumberFormat.getInstance());
field1.setValue(0.4);
frame.add(new JLabel("value A"));
frame.add(field1);

JFormattedTextField field2 = new JFormattedTextField(NumberFormat.getInstance());
field2.setValue(0.8);
frame.add(new JLabel("value B"));
frame.add(field2);

frame.setVisible(true);

который генерирует:

введите здесь описание изображения

Цель

Когда я нажимаю/сосредотачиваюсь на любом из JFormattedTextField, я бы хотел, чтобы он автоматически помещал каретку в конце

введите здесь описание изображения введите здесь описание изображения

Проблема

Я пытался использовать следующие решения перед вызовом frame.setVisible(true);, но ни одно из них не работает.


person user5327287    schedule 16.03.2019    source источник
comment
Каково содержимое JTextField? Где вы хотите установить курсор и когда это должно произойти?   -  person Pshemo    schedule 17.03.2019
comment
задача которого? больше не работает, не очень помогает - у меня работает (при условии, что ratioField вместо JTextField в первом примере кода)   -  person user85421    schedule 17.03.2019
comment
Пожалуйста, отредактируйте свой вопрос, включив в него минимальный воспроизводимый пример, который может быть скомпилирован и протестирован другими, который показывает, что курсор не установлен в определенной позиции.   -  person Progman    schedule 17.03.2019
comment
я отредактировал сообщение   -  person user5327287    schedule 17.03.2019
comment
Вы утверждали, что это JTextField, но в вашем коде используется JFormattedTextField. Детали могут иметь значение.   -  person Pshemo    schedule 17.03.2019
comment
Это не имеет значения, потому что он расширяет JTextField   -  person user5327287    schedule 18.03.2019
comment
Расширение JTextField не гарантирует такого же поведения (что является основной идеей переопределения методов в подклассах). Я не уверен, что это то, чего вы хотите достичь, но если я вас правильно понимаю, вы хотите, чтобы курсор был установлен после значения с самого начала (с момента отображения кадра). Показанный выше код работает для этого сценария с JTextField, но не с JFormattedTextField. Таким образом, класс экземпляра имеет значение для этого сценария, но может не иметь значения, если это не то, чего вы хотели достичь (если ваша цель отличается, поэтому я спрашивал ранее когда установка курсора должна произойти).   -  person Pshemo    schedule 18.03.2019
comment
Но класс JFormattedTextField не переопределял этот метод, и если он переопределяет, значит, документы оракула упоминают об этом, чего они не делают.   -  person user5327287    schedule 18.03.2019
comment
Его не нужно переопределять. Этот метод описывает только где установить курсор, но не когда его устанавливать (когда его следует вызывать - это решение, похоже, принимается в другом месте, которое, вероятно, переопределено) .   -  person Pshemo    schedule 18.03.2019
comment
Так в чем, по-вашему, проблема?   -  person user5327287    schedule 18.03.2019
comment
Я не знаю, я не гуру свинга, как MadProgrammer (и несколько других здесь), но, по крайней мере, теперь ясно, чего вы хотели добиться, так что, может быть, они разберутся.   -  person Pshemo    schedule 18.03.2019
comment
@user5327287 user5327287 Я попытался упростить ваш вопрос. Дайте мне знать, если я переусердствовал, и вы предпочитаете свою [более раннюю версию] - в этом случае не стесняйтесь откатить мою правку (или, если вы не знаете, как это сделать, дайте мне знать об этом, я сделаю это для вас).   -  person Pshemo    schedule 19.03.2019
comment
Да мне кажется хорошо. Спасибо, я только что изменил слово «курсор» на «каретку».   -  person user5327287    schedule 20.03.2019


Ответы (1)


У меня работает без проблем....

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            JTextField textField = new JTextField("This is a test");
            add(textField, gbc);

            JButton button = new JButton("This is a button");
            add(button, gbc);
            button.setFocusable(false);
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (textField.getCaretPosition() != 0) {
                        textField.setCaretPosition(0);
                    } else {
                        textField.setCaretPosition(textField.getText().length());
                    }
                    textField.requestFocusInWindow();
                }
            });
        }

    }

}

Предоставьте запускаемый пример, который не работает, если у вас все еще есть проблемы.

Обновление с JFormattedTextField....

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            JFormattedTextField textField = new JFormattedTextField("This is a test");
            textField.setValue(0.8d);
            add(textField, gbc);

            JButton button = new JButton("This is a button");
            add(button, gbc);
            button.setFocusable(false);
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (textField.getCaretPosition() != 0) {
                        textField.setCaretPosition(0);
                    } else {
                        textField.setCaretPosition(textField.getText().length());
                    }
                    textField.requestFocusInWindow();
                }
            });
        }

    }

}

Обновлено с установленным в начале

Хорошо, я просто хочу отметить, что лично мне не нравится JFormattedTextField, он иногда делает много вещей, которые не всегда имеют смысл.

Старый трюк, который я использовал при реализации автоматического выбора всех при усилении фокуса, заключается в том, чтобы разгрузить запрос в конец потока диспетчеризации событий, это помещает запрос ПОСЛЕ всех странных вещей, которые JFormattedTextField делает, когда поле становится сфокусированным. ...

JFormattedTextField textField = new JFormattedTextField("This is a test");
textField.setValue(0.8d);
add(textField, gbc);
textField.addFocusListener(new FocusAdapter() {
    @Override
    public void focusGained(FocusEvent arg0) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                textField.setCaretPosition(textField.getText().length());
            }
        });
    }
});

Да я серьезно ...

person MadProgrammer    schedule 17.03.2019
comment
На основании обновления OP кажется, что он использует JFormattedTextField, а не JTextField (несмотря на то, что предлагает заголовок вопроса, РЕДАКТИРОВАТЬ: теперь он изменился). - person Pshemo; 17.03.2019
comment
Это не имеет значения, потому что он расширяет JTextField - person user5327287; 18.03.2019
comment
@Pshemo и @user5327287, которые простираются от JTextComponent, из которого определяется setCaretPosition - person MadProgrammer; 18.03.2019
comment
@MadProgrammer Мне просто интересно, хочет ли OP, чтобы курсор был после значения с самого начала (с момента отображения кадра). Это можно легко сделать с помощью JTextField, но JFormattedTextField, кажется, сбрасывает (я не совсем уверен, что здесь происходит на самом деле, поэтому не знаю, какое слово будет правильным) при запуске, даже если мы явно вызываем textField.setCaretPosition(textField.getText().length()); после textField.setValue(0.8d);. - person Pshemo; 18.03.2019
comment
Но я не хочу, чтобы кнопка выполняла этот код при нажатии. Я пытался использовать OnMouseClick, но он тоже не работает - person user5327287; 18.03.2019
comment
@ user5327287 Тогда, пожалуйста, отредактируйте свой вопрос и объясните, чего вы делаете, чего хотите достичь. Когда и что вы хотите? - person Pshemo; 18.03.2019
comment
@user5327287 user5327287 Видите разницу между вашим примером и моим? Это то, что мы подразумеваем под минимальным, полным, поддающимся проверке примером. - person MadProgrammer; 18.03.2019
comment
Я попробовал этот трюк addFocusListener, и он у меня не сработал. Когда я печатаю положение каретки, он возвращает конец текстового индекса, но в JPanel он все еще показывает его в начале строки. - person user5327287; 18.03.2019
comment
Подождите, неважно, теперь я заметил, что у вас есть EventQueue.invokeLater, который я пропустил. Теперь это работает, спасибо :) - person user5327287; 18.03.2019