2009-07-24 13 views
33

Tengo una pequeña aplicación de escritorio Java que usa Swing. Hay un cuadro de diálogo de entrada de datos con algunos campos de entrada de diferentes tipos (JTextField, JComboBox, JSpinner, JFormattedTextField). Cuando activo JFormattedTextFields, ya sea tabulando el formulario o haciendo clic con el mouse, me gustaría seleccionar todo el texto que contiene actualmente. De esta forma, los usuarios podrían comenzar a escribir y sobrescribir los valores predeterminados.¿Cómo seleccionar todo el texto en un JFormattedTextField cuando se enfoca?

¿Cómo puedo hacer eso? Utilicé FocusListener/FocusAdapter que llama a selectAll() en JFormattedTextField, pero no selecciona nada, aunque se llama al método FocusGained() del FocusAdapter (ver ejemplo de código a continuación).

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

¿Alguna idea? Lo curioso es que la selección de todo su texto aparentemente es el comportamiento predeterminado tanto para JTextField como para JSpinner, al menos cuando se tabula a través del formulario.

Respuesta

65

envolver su llamada con SwingUtilities.invokeLater por lo que sucederá después de todos los eventos AWT pendientes han sido procesados:

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

Gracias, eso es todo. Solo puedo adivinar que NumberFormatter está haciendo algo que deshace el selectAll()? –

+3

Sí lo hace. Formatea el valor y restablece el texto. –

+1

+1 Lo necesitaba, no podía recordar al instante cómo hacerlo yo mismo, busqué en Google e inmediatamente encontré esta respuesta. ¡Gracias! –

6

Eso es porque la JFormattedTextfield anula processFocusEvent para formatear el enfoque ganado/perdido el foco.

Una forma de tiro seguro es extender JFormattedTextField y reemplazar el método processFocusEvent:

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

El uso de un focusListener no siempre podría work..since que dependerá de la hora a la que se llama en relación con el processFocusEvent .

14

Además de lo anterior, si desea que esta para todos los campos de texto que acaba puede hacer:

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

El código de camickr puede ser mejorado ligeramente. Cuando el foco pasa de un JTextField a otro tipo de componente (como un botón), la última selección automática no se borra. Se puede fijar de esta manera:

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

Sé que esto es un poco viejo, pero se le ocurrió una solución más limpia, sin 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

me funciona en todos los casos +1 – mKorbel

Cuestiones relacionadas