2012-04-08 17 views
8

Voi ragazzi erano così impressionante in me punto nella giusta direzione sulla mia ultima domanda e ho una sorta di prolungamento della mia domanda originale qui:Come mantenere il rendering delle cellule JTable dopo modifica delle cellule

How to set a JTable column as String and sort as Double?

Dato che ora ho la mia colonna di prezzo formattata come $ ###, ## 0.00 usando il mio renderer di celle personalizzato, ora ho impostato anche un editor JTextField per la cella. La modifica della cella funziona bene, tranne quando il valore viene aggiornato, il formato numerico impostato nel mio renderizzatore personalizzato non sembra più formattare la cella (sto perdendo il $ dopo che la modifica è stata commessa). Questo renderizzatore non dovrebbe rendere le celle anche dopo la visualizzazione iniziale dei dati?

ho cercato di utilizzare il seguente senza fortuna:

((AbstractTableModel) table.getModel()).fireTableDataChanged(); 

Speravo che questo costringerebbe il tavolo al fine di rinnovare e ridisegnare le celle utilizzando il renderer personalizzato per rendere i nuovi valori, ma questo purtroppo non ha funzionato ...

Mi manca qualcosa ... Ovviamente, ma cosa?

risposta

10

Al termine del tuo editor, il metodo editingStopped() della tabella raccoglie il nuovo valore tramite getCellEditorValue() e lo utilizza nel modello setValueAt(). Il modello, a sua volta, dovrebbe fireTableCellUpdated(), che invocherà il renderer prescritto. Estendere default dovrebbe essere sufficiente per gestire la formattazione Number. In altri casi, può essere conveniente utilizzare un'istanza del tuo renderer come componente del tuo editor; questo example mostra un'implementazione tipica.

Addendum: ecco un esempio di base che utilizza l'editor predefinito e le implementazioni del renderer.

Addendum: Grazie ai commenti utili di @mKorbel, ho aggiornato l'esempio per selezionare il testo della cella da modificare, come descritto nell'articolo Table Select All Editor di @ camickr.

RenderEditNumber

package overflow; 

import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.event.MouseEvent; 
import java.text.NumberFormat; 
import java.util.EventObject; 
import javax.swing.DefaultCellEditor; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.JTextField; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.text.JTextComponent; 

/** @see http://stackoverflow.com/a/10067560/230513 */ 
public class RenderEditNumber extends JPanel { 

    private NumberFormat nf = NumberFormat.getCurrencyInstance(); 

    public RenderEditNumber() { 
     DefaultTableModel model = new DefaultTableModel(
      new String[]{"Amount"}, 0) { 

      @Override 
      public Class<?> getColumnClass(int columnIndex) { 
       return Double.class; 
      } 
     }; 
     for (int i = 0; i < 16; i++) { 
      model.addRow(new Object[]{Double.valueOf(i)}); 
     } 
     JTable table = new JTable(model) { 

      @Override // Always selectAll() 
      public boolean editCellAt(int row, int column, EventObject e) { 
       boolean result = super.editCellAt(row, column, e); 
       final Component editor = getEditorComponent(); 
       if (editor == null || !(editor instanceof JTextComponent)) { 
        return result; 
       } 
       if (e instanceof MouseEvent) { 
        EventQueue.invokeLater(new Runnable() { 

         @Override 
         public void run() { 
          ((JTextComponent) editor).selectAll(); 
         } 
        }); 
       } else { 
        ((JTextComponent) editor).selectAll(); 
       } 
       return result; 
      } 
     }; 
     table.setPreferredScrollableViewportSize(new Dimension(123, 123)); 
     table.setDefaultRenderer(Double.class, new CurrencyRenderer(nf)); 
     table.setDefaultEditor(Double.class, new CurrencyEditor(nf)); 
     this.add(new JScrollPane(table)); 
    } 

    private static class CurrencyRenderer extends DefaultTableCellRenderer { 

     private NumberFormat formatter; 

     public CurrencyRenderer(NumberFormat formatter) { 
      this.formatter = formatter; 
      this.setHorizontalAlignment(JLabel.RIGHT); 
     } 

     @Override 
     public void setValue(Object value) { 
      setText((value == null) ? "" : formatter.format(value)); 
     } 
    } 

    private static class CurrencyEditor extends DefaultCellEditor { 

     private NumberFormat formatter; 
     private JTextField textField; 

     public CurrencyEditor(NumberFormat formatter) { 
      super(new JTextField()); 
      this.formatter = formatter; 
      this.textField = (JTextField) this.getComponent(); 
      textField.setHorizontalAlignment(JTextField.RIGHT); 
      textField.setBorder(null); 
     } 

     @Override 
     public Object getCellEditorValue() { 
      try { 
       return new Double(textField.getText()); 
      } catch (NumberFormatException e) { 
       return Double.valueOf(0); 
      } 
     } 

     @Override 
     public Component getTableCellEditorComponent(JTable table, 
      Object value, boolean isSelected, int row, int column) { 
      textField.setText((value == null) 
       ? "" : formatter.format((Double) value)); 
      return textField; 
     } 
    } 

    private void display() { 
     JFrame f = new JFrame("RenderEditNumber"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(this); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new RenderEditNumber().display(); 
      } 
     }); 
    } 
} 
+0

+1 ma ho visto che prima non funziona correttamente se si desidera aggiungere, rimuovere o modificare il valore che esiste, Editor ritorna 0.00 :-), avrei dovuto guardare ... – mKorbel

+0

Buon punto. Per l'input della matrice, l'editor restituisce intenzionalmente zero su 'NumberFormatException'; 'cancelCellEditing()' sarebbe un'alternativa più generale. – trashgod

+0

questo è lo stesso per JFormattedTextField o JSpinner come CellEditor, sono sicuro che Rob ha ottenuto ..., lì devi restituire Document, Rob dove sei :-) – mKorbel

Problemi correlati