2012-04-08 18 views
8

Ustedes eran tan impresionante en mí el punto en la dirección correcta en mi última pregunta y tengo una especie de extensión de mi pregunta original aquí:Cómo mantener la prestación de células JTable después de edición de celda

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

Como ahora tengo mi columna de precios formateada como $ ###, ## 0.00 mediante el uso de mi procesador de células personalizado, ahora también he configurado un Editor de JTextField para la celda. La edición de la celda funciona bien, excepto cuando el valor se actualiza, el formato de número establecido en mi procesador personalizado ya no parece formatear la celda (estoy perdiendo la $ después de la edición se confirma). ¿No se supone que este renderizador renderiza las celdas incluso después de la visualización inicial de los datos?

me han tratado de usar la siguiente sin suerte:

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

Yo esperaba que esto obligaría a la mesa para revalidar y volver a pintar las células utilizando el intérprete personalizado para hacer que los nuevos valores, pero esto lamentablemente no funcionó ...

Me falta algo ... Obviamente, ¿pero qué?

Respuesta

10

Cuando el editor concluye, el método editingStopped() de la tabla recopila el nuevo valor a través de getCellEditorValue() y lo usa en setValueAt() en el modelo. El modelo, a su vez, debe fireTableCellUpdated(), que invocará el renderizador prescrito. La extensión de default debería ser suficiente para manejar el formato Number. En otros casos, puede ser conveniente usar una instancia de su procesador como su componente editor; este example muestra una implementación típica.

Adición: Aquí hay un ejemplo básico usando las implementaciones predeterminadas del editor y del procesador.

Adición: Gracias a los útiles comentarios de @mKorbel, he actualizado el ejemplo para seleccionar el texto de la celda para su edición, como se describe en el artículo de @campickr Table Select All Editor.

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, pero he visto que antes no funciona correctamente si desea añadir, eliminar o editar el valor que existe, Editor vuelve 0.00 :-), tendría que mirar ... – mKorbel

+0

Buen punto. Para la entrada de matriz, el editor intencionalmente devuelve cero en 'NumberFormatException'; 'cancelCellEditing()' sería una alternativa más general. – trashgod

+0

esto es lo mismo para JFormattedTextField o JSpinner como CellEditor, estoy seguro de que Rob tiene ..., tienes que devolver el documento, Rob, dónde estás :-) – mKorbel

Cuestiones relacionadas