2009-07-24 18 views
33

Ich habe eine kleine Java-Desktop-App, die Swing verwendet. Es gibt einen Dateneingabe-Dialog mit einigen Eingabefeldern unterschiedlicher Typen (JTextField, JComboBox, JSpinner, JFormattedTextField). Wenn ich die JFormattedTextFields entweder durch Tabulatoren durch das Formular oder durch Klicken mit der Maus aktiviere, möchte ich, dass es den gesamten Text auswählt, den es gerade enthält. Auf diese Weise könnten Benutzer einfach mit der Eingabe beginnen und die Standardwerte überschreiben.Wie wird der gesamte Text in einem JFormattedTextField ausgewählt, wenn er den Fokus erhält?

Wie kann ich das tun? Ich habe einen FocusListener/FocusAdapter verwendet, der selectAll() auf dem JFormattedTextField aufruft, aber nichts auswählt, obwohl die focusGained() -Methode des FocusAdapters aufgerufen wird (siehe Codebeispiel unten).

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

Irgendwelche Ideen? Das Lustige ist, dass die Auswahl des gesamten Textes anscheinend das Standardverhalten für JTextField und JSpinner ist, zumindest wenn man das Formular durchsucht.

Antwort

65

Wickeln Sie Ihren Anruf mit SwingUtilities.invokeLater so dass es, nachdem alle anstehenden AWT Ereignisse verarbeitet wurden passieren wird:

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

Danke, das ist es. Ich kann nur vermuten, dass der NumberFormatter etwas tut, das die selectAll() rückgängig macht? –

+3

Ja, tut es. Es formatiert den Wert und setzt den Text zurück. –

+1

+1 Benötigte dies, konnte mich nicht sofort daran erinnern, wie ich das selbst machen konnte, googelte und fand sofort diese Antwort. Vielen Dank! –

6

Das ist, weil die JFormattedTextField processFocusEvent überschreibt den Fokus verloren gewonnen/Fokus zu formatieren auf.

Ein sicherer Schuss Weg ist JFormattedTextField zu erweitern und die processFocusEvent Methode überschreiben:

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

ein focuslistener verwenden, kann es nicht immer work..since würde von der Zeit abhängen, an dem sie in Bezug auf die processFocusEvent genannt wird .

14

Zusätzlich zu den oben genannten, wenn Sie dies für alle Textfelder möchten, können Sie einfach tun:

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

     } 
    } 
}); 
2

Der Code von camickr leicht verbessert werden kann. Wenn der Fokus von einem JTextField auf eine andere Art von Komponente (eine solche Schaltfläche) übergeht, wird die letzte automatische Auswahl nicht gelöscht. Es kann auf diese Weise festgelegt werden:

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

      } 
     } 
    }); 
7

Ich weiß, diese Art von alt ist, aber ich kam mit einer Reinigungslösung auf, ohne 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(); 
     } 
    } 

} 
+0

für mich in allen Fällen +1 – mKorbel

Verwandte Themen