Reputation: 4152
I have a small Java desktop app that uses Swing. There is a data entry dialog with some input fields of different types (JTextField, JComboBox, JSpinner, JFormattedTextField). When I activate the JFormattedTextFields either by tabbing through the form or by clicking it with the mouse, I would like it to select all the text that it currently contains. That way, users could just start typing and overwrite the default values.
How can I do that? I did use a FocusListener/FocusAdapter that calls selectAll() on the JFormattedTextField, but it doesn't select anything, although the FocusAdapter's focusGained() method is called (see code sample below).
private javax.swing.JFormattedTextField pricePerLiter;
// ...
pricePerLiter.setFormatterFactory(
new JFormattedTextField.AbstractFormatterFactory() {
private NumberFormatter formatter = null;
public JFormattedTextField.AbstractFormatter
getFormatter(JFormattedTextField jft) {
if (formatter == null) {
formatter = new NumberFormatter(new DecimalFormat("#0.000"));
formatter.setValueClass(Double.class);
}
return formatter;
}
});
// ...
pricePerLiter.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
pricePerLiter.selectAll();
}
});
Any ideas? The funny thing is that selecting all of its text apparently is the default behavior for both JTextField and JSpinner, at least when tabbing through the form.
Upvotes: 37
Views: 38788
Reputation: 2797
I know this is kind of old, but I came up with a cleaner solution, without invokeLater:
private class SelectAllOfFocus extends FocusAdapter {
@Override
public void focusGained(FocusEvent e) {
if (! e.isTemporary()) {
JFormattedTextField textField = (JFormattedTextField)e.getComponent();
// This is needed to put the text field in edited mode, so that its processFocusEvent doesn't
// do anything. Otherwise, it calls setValue, and the selection is lost.
textField.setText(textField.getText());
textField.selectAll();
}
}
}
Upvotes: 7
Reputation: 17369
Wrap your call with SwingUtilities.invokeLater so it will happen after all pending AWT events have been processed :
pricePerLiter.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
pricePerLiter.selectAll();
}
});
}
});
Upvotes: 71
Reputation: 21
The code of camickr can be slightly improved. When the focus passes from a JTextField to another kind of component (such a button), the last automatic selection does not get cleared. It can be fixed this way:
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener()
{
@Override
public void propertyChange(final PropertyChangeEvent e)
{
if (e.getOldValue() instanceof JTextField)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JTextField oldTextField = (JTextField)e.getOldValue();
oldTextField.setSelectionStart(0);
oldTextField.setSelectionEnd(0);
}
});
}
if (e.getNewValue() instanceof JTextField)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JTextField textField = (JTextField)e.getNewValue();
textField.selectAll();
}
});
}
}
});
Upvotes: 2
Reputation: 324128
In addition to the above, if you want this for all text fields you can just do:
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener()
{
public void propertyChange(final PropertyChangeEvent e)
{
if (e.getNewValue() instanceof JTextField)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JTextField textField = (JTextField)e.getNewValue();
textField.selectAll();
}
});
}
}
});
Upvotes: 15
Reputation: 217
Thats because the JFormattedTextfield overrides processFocusEvent to format on focus gained/focus lost.
One sure shot way is to extend JFormattedTextField and override the processFocusEvent method :
new JFormattedTextField("...") {
protected void processFocusEvent(FocusEvent e) {
super.processFocusEvent(e);
if (e.isTemporary())
return;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
selectAll();
}
});
}
};
Using a focusListener might not always work..since it would depend on the time at which it is called relative to the processFocusEvent.
Upvotes: 7