2012-04-08 18 views
8

Ihre Jungs waren so genial in Punkt mich in der richtigen Richtung auf meiner letzten Frage und ich habe irgendwie eine Erweiterung meiner ursprünglichen Frage hier erhalten:Wie JTable Zelle Rendering nach Zelle bearbeitet

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

Da ich nun meine Preisspalte mit meinem benutzerdefinierten CellRenderer als $ ###, ## formatiert habe, habe ich jetzt auch einen JTextField-Editor für die Zelle eingerichtet. Die Bearbeitung der Zelle funktioniert einwandfrei, außer wenn der Wert aktualisiert wird, scheint das Zahlenformat, das in meinem benutzerdefinierten Renderer eingestellt ist, die Zelle nicht mehr zu formatieren (ich verliere die $ nach der Bearbeitung ist committed). Soll dieser Renderer die Zellen auch nach der ersten Anzeige der Daten nicht rendern?

Ich habe versucht, den folgenden ohne Glück zu verwenden:

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

Ich habe gehofft, dass diese auf den Tisch zwingen würden, die Zellen mit den benutzerdefinierten Renderer die neuen Werte, aber leider revalidate und neu streichen zu machen hat nicht funktioniert ...

Fehle ich etwas ... Offensichtlich, aber was?

Antwort

10

Wenn Ihr Editor schließt, die Tabelle editingStopped() Methode sammelt den neuen Wert über getCellEditorValue() und verwendet es zu setValueAt() im Modell. Das Modell sollte wiederum fireTableCellUpdated(), die den vorgeschriebenen Renderer aufrufen wird. Erweitern Sie die default sollte genug sein, um Number Formatierung zu behandeln. In anderen Fällen kann es sinnvoll sein, eine Instanz des Renderers als Editorkomponente zu verwenden. Diese example zeigt eine typische Implementierung.

Addendum: Hier ist ein grundlegendes Beispiel mit den Standard-Editor und Renderer-Implementierungen.

Nachtrag: Dank hilfreicher Kommentare von @mKorbel, habe ich das Beispiel aktualisiert, um den Text der Zelle zur Bearbeitung auszuwählen, wie in @ camickrs Artikel Table Select All Editor beschrieben.

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, aber ich sah, dass vor nicht richtig funktioniert, wenn Sie hinzufügen möchten, entfernen oder zu bearbeiten Wert, die vorhanden sind, Editor 0.00 :-) gibt, würde ich schauen müssen ... . – mKorbel

+0

Guter Punkt. Bei Matrixeingaben gibt der Editor absichtlich null für "NumberFormatException" zurück; 'cancelCellEditing()' wäre eine allgemeinere Alternative. – trashgod

+0

Das ist das selbe für JFormattedTextField oder JSpinner wie CellEditor, ich bin mir sicher, dass Rob ..., da musst du Document zurückgeben, Rob wo bist du :-) – mKorbel

Verwandte Themen