Search code examples
javaswingcaretjformattedtextfield

How to set caret position at the end of JFormattedTextField when it is clicked/focused?


I have frame with JFormattedTextField(s). My simplified code can look like:

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

which generates:

enter image description here

Goal

When I click/focus on any of JFormattedTextField I would like it to automatically place caret at the end

enter image description here enter image description here

Problem

I tried using following solutions before calling frame.setVisible(true); but none of them seems to work


Solution

  • Works without issue for me....

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

    Provide a runnable example which doesn't work if you still have issues

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

    Updated with "set at beginning"

    Okay, I just want to point out that I have personally dislike of JFormattedTextField, it does a lot of "things" at times which don't always make sense.

    An "old" trick I've used, when implementing a "auto select all on focus gain", is to offload the request to the end of the Event Dispatching Thread, this places the request AFTER all the "funky stuff" that the JFormattedTextField does when the field becomes focused...

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

    Yes, I'm serious ...