6

By default, when a JTextField gains focus the caret is positioned at the beginning of the text. However, I think the better behavior is to position it at the end, or to select all the text, e.g. http://jsfiddle.net/Marcel/jvJzX/. What is a nice way to do this? Ideally, the solution would be applied globally to all JTextFields in the application.

Example of the default behavior (hit tab to focus the field):

public static void main(String[] args) {
    JTextField field = new JTextField("hello world!");
    JOptionPane.showMessageDialog(null, field);
}

Edit: To clarify, it would be nice if I didn't have to search through my app and change all the text fields.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Peter Tseng
  • 13,613
  • 4
  • 67
  • 57
  • either that or position the cursor at the end – Peter Tseng Jul 03 '13 at 07:40
  • thats could be signoficant difference, (my view) there are two ways move with Caret to the end of Document see answer by @MadProgrammer or selectAll() see my comment in (@MadProgrammer) post – mKorbel Jul 03 '13 at 07:54

3 Answers3

9

Neither the actual behaviour nor the requirement are fully described:

when a JTextField gains focus the caret is positioned at the beginning of the text

that's not entirely true: when it gains focus by

  • clicking, the caret is placed at the mouse location
  • other means (tabbing, programmatic) it is placed at the position it had at the time focus was lost.

Consequently, the requirement:

the better behavior is to position it at the end, or to select all the text

needs a bit of thought for those cases to not detoriate usability, at least for the first users might be confused if a mouse gesture would be overruled. The second is arguable and probably OS/LAF dependent. Personally, I wouldn't touch the caret if its position is not at the start.

Technically, a solution to globally trigger changes of component state on focus changes is to register a PropertyChangeListener with the KeyboardFocusManager:

PropertyChangeListener pl = new PropertyChangeListener() {

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (!(evt.getNewValue() instanceof JTextField)) return;
        JTextField field = (JTextField) evt.getNewValue();
        // crude check to not overdo it
        int dot = field.getCaretPosition();
        if (dot == 0) {
            field.selectAll();
        }
    }
};
KeyboardFocusManager.getCurrentKeyboardFocusManager()
    .addPropertyChangeListener("permanentFocusOwner", pl);
kleopatra
  • 51,061
  • 28
  • 99
  • 211
  • 3
    +1 for easy global solution. The `selectAll()` should probably be wrapped in a SwingUtilities.invokeLater() otherwise the selection on a JFormattedTextField won't work. – camickr Jul 03 '13 at 14:54
  • @camickr good point! Though not entirely certain about the usability of a formattedTextField - it's navigationFilter may have its own ideas? – kleopatra Jul 03 '13 at 15:01
  • 1
    +1 - You may also want to check if `event.getOldValue()` is a JTextField so as to undo the `selectAll()`. – splungebob Jul 03 '13 at 16:04
  • @splungebob good point to think about! Might depend on concrete requirement, though - not entirely sure if we always want to unselect, even if all is selected in the old field? – kleopatra Jul 04 '13 at 13:34
4

Add a FocusListener to the field

When focusGained is triggered, set the caret position of the field to the end of the text...

field.setCaretPosition(field.getDocument().getLength());

See How to write a focus listener for more details

Updated

To select all the text, you can use...

field.selectAll();

Which will move the cursor to the end.

What I've done in the past is create a utility class (AutoSelectOnFocusManager for example), which has a single FocusListener. Basically, you register (or unregister) JTextComponents with it and it manages the process for you. Saves a lot of repeated code :P

Updated with a simple example

Did this simple example to test the feedback in the comments, thought I'd just whack in as well...

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Wackme {

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

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

                JTextField field1 = new JTextField("Some text", 20);
                JTextField field2 = new JTextField("Some text", 20);

                field1.addFocusListener(new FocusAdapter() {
                    @Override
                    public void focusGained(FocusEvent e) {
                        System.out.println("Move to end");
                        JTextField field = ((JTextField)e.getComponent());
                        field.selectAll();
                        //field.setCaretPosition(field.getDocument().getLength());
                    }
                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                frame.add(field1);
                frame.add(field2);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • I think that should be `field.getDocument().getLength() - 1` –  Jul 03 '13 at 07:31
  • 1
    @MadProgrammer [I think that](http://stackoverflow.com/a/8544512/714968), but XXX.selectAll() required to be wrapped into `invokeLater` – mKorbel Jul 03 '13 at 07:42
  • 1
    @mKorbel It depends, I know if it's a `JSpinner` it DEFINITELY does – MadProgrammer Jul 03 '13 at 07:55
  • I believe the invokeLater is required when a JFormattedTextField is used either by itself or as an editor for another component. – camickr Jul 03 '13 at 14:56
-2

you need to create your custom jtextfield and override necessary methods that you want and perform steps like you want to select all the values on focus gained then write your code in that method

shreyansh jogi
  • 2,082
  • 12
  • 20