2011-11-17 53 views
10

El comportamiento predeterminado de una JTable es agregar los contenidos cuando comienza a escribir, y colocar el símbolo de intercalación en la ubicación en la que se hace clic al hacer clic. Quiero que el comportamiento de ambas cosas cambie, por lo que el contenido se reemplaza cuando edito una celda, ya sea escribiendo o haciendo clic y luego escribiendo. Sin embargo, cuando hago clic en una celda y luego cambio la posición de intercalación, quiero que el contenido permanezca así puedo cambiarlo.¿Cómo seleccionar todo el texto en la celda JTable al editar pero no al tipear?

Sé cómo seleccionar todo cuando la celda se está editando, reemplazando el editor de celda con uno que selecciona todo dentro de SwingUtilities.invokeLater (ver elsewhere), pero eso hace que el comportamiento de tipeo se rompa. Cuando hago esto y empiezo a escribir en una celda, primero se agrega el carácter mecanografiado a la cadena, luego se selecciona (¡pero la selección es invisible!) Y cuando se escribe otro carácter, el contenido se reemplaza por eso.

¿Hay alguna forma de reemplazar el contenido inmediatamente al escribir en una celda resaltada (pero sin editar), pero seleccionar todo al hacer clic en una celda?

Este es el código que utilizo para la CellEditor:

public class TextFieldCellEditor extends JTextField implements TableCellEditor 
{ 
    private CellEditorListener cellEditorListener = null; 

    private boolean    isInteger   = false; 
    private Object    oldValue; 

    // Start editing 
    @Override 
    public Component getTableCellEditorComponent(JTable table, Object obj, boolean isSelected, int row, int column) 
    { 
     Color color2 = DefaultLookup.getColor(this, ui, "Table.alternateRowColor"); 
     super.setBackground(color2 != null && (row & 1) == 1? color2 : table.getBackground()); 
     super.setForeground(table.getForeground()); 
     super.setBorder(DefaultLookup.getBorder(this, ui, "Table.focusCellHighlightBorder")); 

     super.setText(obj.toString()); 

     isInteger = obj instanceof Integer; 
     if (isInteger) 
     { 
      super.setHorizontalAlignment(SwingConstants.RIGHT); 
      oldValue = obj; 
     } 

     // SwingUtilities.invokeLater(new Runnable() 
     // { 
     // public void run() 
     // { 
     // TextFieldCellEditor.this.selectAll(); 
     // } 
     // }); 

     return this; 
    } 

    // Retrieve e dited value 
    @Override 
    public Object getCellEditorValue() 
    { 
     if (isInteger) 
     { 
      // Try to convert to integer. If input is invalid, revert. 
      try 
      { 
       return new Integer(super.getText()); 
      } 
      catch (NumberFormatException e) 
      { 
       return oldValue; 
      } 
     } 
     return super.getText(); 
    } 

    @Override 
    public boolean isCellEditable(EventObject e) 
    { 
     return true; 
    } 

    @Override 
    public boolean shouldSelectCell(EventObject e) 
    { 
     return true; 
    } 

    @Override 
    public boolean stopCellEditing() 
    { 
     cellEditorListener.editingStopped(new ChangeEvent(this)); 
     return true; 
    } 

    @Override 
    public void cancelCellEditing() 
    { 
     cellEditorListener.editingCanceled(new ChangeEvent(this)); 
    } 

    @Override 
    public void addCellEditorListener(CellEditorListener celleditorlistener) 
    { 
     cellEditorListener = celleditorlistener; 
    } 

    @Override 
    public void removeCellEditorListener(CellEditorListener celleditorlistener) 
    { 
     if (cellEditorListener == cellEditorListener) cellEditorListener = null; 
    } 
} 
+0

esta implementación no es válida: a) no admite la adición de más de un oyente b) no notifica a su oyente cuando se detiene/cancela por _ razones internas (por ejemplo, presionando Intro) Consulte la fuente de DefaultCellEditor para tener una idea de lo que se necesita – kleopatra

+0

Than Kansas. Arreglado. –

Respuesta

2

En su aplicación getTableCellEditorComponent(), añada lo siguiente:

if (isSelected) { 
    this.selectAll(); 
} 

Como acotación al margen, por qué no extender AbstractCellEditor o DefaultCellEditor(JTextField textField)? Consulte también How to Use Tables: Using Other Editors.

Adición: Vea también Table Select All Renderer y Table Select All Editor.

+0

Gracias. Pensé que isSelected siempre sería cierto ya que navegué a la celda, ya sea con el teclado o con el mouse, así que lo ignoré. –

+0

Experimenté extendiendo AbstractCellEditor en el pasado pero eventualmente me conformé con esto. No sé por qué más. –

+0

Lo cambié de nuevo debido a los oyentes (ver el comentario anterior) y que el campo 'ui' está protegido dentro de' JTextField', así que es por eso que lo hice de esta manera. Demonios, ni siquiera sé por qué utilicé (como descubrí ahora) la desalentada clase 'DefaultLookup' en lugar de' UIManager' (probablemente copié algún código novato de los internets) –

0

La solución más limpia que pude encontrar para este caso fue para sobrescribir editCellAt del JTable e informar a la CellEditor de cómo se desencadenó la edición:

@Override 
public boolean editCellAt(int row, int column, EventObject e) { 
    cellEditor.setKeyTriggered(e instanceof KeyEvent); 
    return super.editCellAt(row, column, e); 
} 

Y aquí está el código CellEditor relevante:

public class MyCellEditor extends DefaultCellEditor { 

    private boolean keyTriggered; 

    public MyCellEditor() { 
     super(new JTextField()); 
     final JTextField textField = (JTextField) getComponent(); 
     textField.addFocusListener(new FocusAdapter() { 
      @Override 
      public void focusGained(FocusEvent e) { 
       SwingUtilities.invokeLater(new Runnable() { 
        @Override 
        public void run() { 
         if (!keyTriggered) { 
          textField.selectAll(); 
         } 
        } 
       }); 
      } 
     }); 
    } 

    public void setKeyTriggered(boolean keyTriggered) { 
     this.keyTriggered = keyTriggered; 
    } 

    @Override 
    public Component getTableCellEditorComponent(
      JTable table, Object value, boolean isSelected, int row, int column) { 
     final JTextField textField = (JTextField) 
       super.getTableCellEditorComponent(table, value, isSelected, row, column); 
     textField.selectAll(); 
     return textField; 
    } 
} 
Cuestiones relacionadas