2011-11-17 21 views
10

Il comportamento predefinito di una tabella può essere aggiunto al contenuto quando si inizia a digitare e per posizionare il punto di inserimento nella posizione cliccata quando si fa clic. Voglio che il comportamento di entrambe queste cose cambi, quindi il contenuto viene sostituito quando modifico una cella, digitando o facendo clic e quindi digitando. Quando faccio clic su una cella e poi cambio la posizione del cursore, tuttavia, voglio che il contenuto rimanga così posso cambiarlo.Come selezionare tutto il testo nella cella JTable durante la modifica ma non durante la digitazione?

So come selezionare tutto quando la cella diventa in fase di modifica, sostituendo l'editor di celle con uno che seleziona tutto all'interno di SwingUtilities.invokeLater (vedere elsewhere), ma questo causa la rottura del comportamento di battitura. Quando faccio questo e inizio a digitare in una cella, prima il carattere digitato viene aggiunto alla stringa, quindi viene selezionato (ma la selezione è invisibile!) E quando si digita un altro carattere il contenuto viene sostituito da quello.

C'è un modo per sostituire il contenuto immediatamente quando si digita una cella evidenziata (ma non in modifica), ma si seleziona tutto quando si fa clic su una cella?

ecco il codice che uso per il 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

questa implementazione non è valida: a) non supporta l'aggiunta di più di un listener b) non notifica l'ascoltatore quando viene arrestato/annullato per motivi _internal_ (come fi premendo enter) Vedi l'origine di DefaultCellEditor per avere un'idea di cosa è necessario – kleopatra

+0

Than ks. Aggiustato. –

risposta

2

Nella tua getTableCellEditorComponent() implementazione, aggiungere il seguente:

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

Per inciso, perché non estendere AbstractCellEditor o DefaultCellEditor(JTextField textField)? Vedi anche How to Use Tables: Using Other Editors.

Addendum: vedere anche Table Select All Renderer e Table Select All Editor.

+0

Grazie. Ho pensato che l'opzione Select fosse sempre vera da quando ho navigato nella cella, sia con la tastiera o con il mouse, quindi l'ho ignorata. –

+0

Ho sperimentato l'estensione di AbstractCellEditor in passato, ma alla fine mi sono deciso su questo. Non so perché più. –

+0

Lo ho scambiato di nuovo a causa degli ascoltatori (vedi commento sopra) e che il campo 'ui' è protetto all'interno di' JTextField', ecco perché l'ho fatto in questo modo. Diavolo, non so nemmeno perché ho usato la classe (come ho scoperto ora) scoraggiata 'DefaultLookup' invece di' UIManager' (probabilmente ho copiato qualche codice di noob dagli interni) –

0

la soluzione più pulita che ho trovato per questo caso è stato quello di sovrascrivere editCellAt del JTable e informare il CellEditor di come la modifica è stata innescata:

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

Ed ecco il codice CellEditor rilevanti:

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; 
    } 
} 
Problemi correlati