Is there an easy way to change the behavior of a Java/Swing control when it gets focus?

Question!

For most GUI's I've used, when a control that contains text gets the focus, the entire contents of the control are selected. This means if you just start typing, you completely replace the former contents.

Example: You have spin control that is initialized with the value zero. You tab to it and type "1" The value in the control is now 1.

With Swing, this doesn't happen. The text in the control is not selected and the carat appears at one end or another of the existing text. Continuing the above example:

With a Swing JSpinner, when you tab to the spin control, the carat is at the left. You type "1" and the value in the control is now 10.

This drives me, (and my users) up a wall, and I'd like to change it. Even more important, I'd like to change it globally so the new behavior applies to JTextField, JPasswordField, JFormattedTextField, JTextArea, JComboBox, JSpinner, and so on. The only way I have found to do this to add a FocusAdapter to each control and override the focusGained() method to Do The Right Thing[tm].

There's gotta be an easier, and less fragile way. Please?

EDIT: One additional piece of information for this particular case. The form I am working with was generated using Idea's form designer. That means I normally don't actually write the code to create the components. It is possible to tell Idea that you want to create them yourself, but that's a hassle I'd like to avoid.

Motto: All good programmers are basically lazy.



Answers

After reading the replies so far (Thanks!) I passed the outermost JPanel to the following method:

void addTextFocusSelect(JComponent component){
    if(component instanceof JTextComponent){
        component.addFocusListener(new FocusAdapter() {
                @Override
                public void focusGained(FocusEvent event) {
                    super.focusGained(event);
                    JTextComponent component = (JTextComponent)event.getComponent();
                    // a trick I found on JavaRanch.com
                    // Without this, some components don't honor selectAll
                    component.setText(component.getText());
                    component.selectAll();
                }
            });

    }
    else
    {
        for(Component child: component.getComponents()){
            if(child instanceof JComponent){
                addTextFocusSelect((JComponent) child);
            }
        }
    }
}

It works!



A separate class that attaches a FocusListener to the desired text field can be written. All the focus listener would do is call selectAll() on the text widget when it gains the focus.

public class SelectAllListener implements FocusListener {
  private static INSTANCE = new SelectAllListener();

  public void focusLost(FocusEvent e) { }

  public void focusGained(FocusEvent e) {
    if (e.getSource() instanceof JTextComponent) {  
      ((JTextComponent)e.getSource()).selectAll();
    }
  };

  public static void addSelectAllListener(JTextComponent tc) {
    tc.addFocusListener(INSTANCE);
  }

  public static void removeSelectAllListener(JTextComponent tc) {
    tc.removeFocusListener(INSTANCE);
  }
}

By accepting a JTextComponent as an argument this behavior can be added to JTextArea, JPasswordField, and all of the other text editing components directly. This also allows the class to add select all to editable combo boxes and JSpinners, where your control over the text editor component may be more limited. Convenience methods can be added:

public static void addSelectAllListener(JSpinner spin) {
  if (spin.getEditor() instanceof JTextComponent) {
    addSelectAllListener((JTextComponent)spin.getEditor());
  }
}

public static void addSelectAllListener(JComboBox combo) {
  JComponent editor = combo.getEditor().getEditorComponent();
  if (editor instanceof JTextComponent) {
    addSelectAllListener((JTextComponent)editor);
  }
}

Also, the remove listener methods are likely unneeded, since the listener contains no exterior references to any other instances, but they can be added to make code reviews go smoother.

By : shemnon


I haven't tried this myself (only dabbled in it a while ago), but you can probably get the current focused component by using: KeyboardFocusManager (there is a static method getCurrentKeyboardFocusManager()) an adding a PropertyChangeListener to it. From there, you can find out if the component is a JTextComponent and select all text.

By : Avrom


This video can help you solving your question :)
By: admin