Comment sélectionner tout le texte d’un JFormattedTextField lorsqu’il obtient le focus?

J’ai une petite application de bureau Java qui utilise Swing. Il existe une boîte de dialog de saisie de données avec des champs de saisie de différents types (JTextField, JComboBox, JSpinner, JFormattedTextField). Lorsque j’active le JFormattedTextFields soit en faisant défiler le formulaire, soit en cliquant dessus avec la souris, j’aimerais qu’il sélectionne tout le texte qu’il contient actuellement. De cette façon, les utilisateurs peuvent simplement commencer à taper et remplacer les valeurs par défaut.

Comment puis je faire ça? J’ai utilisé un FocusListener / FocusAdapter qui appelle selectAll () sur JFormattedTextField, mais il ne sélectionne rien, bien que la méthode focusGained () de FocusAdapter soit appelée (voir l’exemple de code ci-dessous).

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

Des idées? La chose amusante est que la sélection de tout son texte est apparemment le comportement par défaut à la fois pour JTextField et JSpinner, du moins lors de la tabulation du formulaire.

    Enveloppez votre appel avec SwingUtilities.invokeLater pour que cela se produise après le traitement de tous les événements AWT en attente:

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

    En plus de ce qui précède, si vous le souhaitez pour tous les champs de texte, vous pouvez simplement:

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

    Je sais que c’est un peu vieux, mais j’ai trouvé une solution plus propre, sans 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(); } } } 

    C’est parce que JFormattedTextfield a priorité sur processFocusEvent pour formater le focus gagné / focus perdu.

    Un moyen sûr est d’étendre JFormattedTextField et de remplacer la méthode processFocusEvent:

     new JFormattedTextField("...") { protected void processFocusEvent(FocusEvent e) { super.processFocusEvent(e); if (e.isTemporary()) return; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { selectAll(); } }); } }; 

    L’utilisation d’un focusListener peut ne pas toujours fonctionner … dans la mesure où cela dépend du moment où il est appelé par rapport à processFocusEvent.

    Le code de camickr peut être légèrement amélioré. Lorsque le focus passe d’un JTextField à un autre type de composant (un bouton, par exemple), la dernière sélection automatique n’est pas effacée. Il peut être corrigé de cette façon:

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