Question

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.

Était-ce utile?

La solution

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

Autres conseils

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

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top