2010-07-26 4 views
11

J'aimerais que mon JTable utilise différents éditeurs de cellules pour différentes cellules dans une seule colonne. Pense que d'une table étiquette de valeur à deux colonnes comme:JTable - éditeurs de cellules multiples dans une colonne

Name   | Value 
--------------+-------------------------------- 
Identifier | ST33442 (string editor) 
Purchase Date | 7/7/10 (custom calendar editor) 
Status  | Broken (combo editor) 

Comment puis-je construire l'éditeur dynamique? Quelque chose comme un TableCellEditorFactory serait parfait.

Répondre

8

Vous devez implémenter votre propre éditeur de cellule et l'affecter à la colonne. Vous devriez probablement faire la même chose avec un renderer de cellule (par exemple, les booléens seront rendus comme une case à cocher au lieu de "true"/"false").

public class TableEditorTest { 

    public static void main(String[] args) { 
     Object[][] data = new Object[][] {{"Identifier", "ST33442"}, {"Purchase Date", new Date()}, {"Status", Boolean.FALSE}}; 
     String[] columnNames = new String[] {"Name", "Value"}; 
     TableModel model = new DefaultTableModel(data, columnNames); 
     JTable table = new JTable(model); 
     JScrollPane scrollPane = new JScrollPane(table); 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(scrollPane); 
     frame.pack(); 
     frame.setVisible(true); 

     table.getColumnModel().getColumn(1).setCellEditor(new CustomTableCellEditor()); 
    } 

    public static class CustomTableCellEditor extends AbstractCellEditor implements TableCellEditor { 
     private TableCellEditor editor; 

     @Override 
     public Object getCellEditorValue() { 
      if (editor != null) { 
       return editor.getCellEditorValue(); 
      } 

      return null; 
     } 

     @Override 
     public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { 
      if (value instanceof Date) { 
       editor = new DatePickerCellEditor(); 
      } else if (value instanceof String) { 
       editor = new DefaultCellEditor(new JTextField()); 
      } else if (value instanceof Boolean) { 
       editor = new DefaultCellEditor(new JCheckBox()); 
      } 

      return editor.getTableCellEditorComponent(table, value, isSelected, row, column); 
     } 
    } 
} 

N.B. DatePickerCellEditor est de SwingX

1

Je viens à une autre solution, puisque je voulais réutiliser les éditeurs par défaut ... La classe suivante redéfinit le getColumnClass pour avoir une réponse différente. Pour autant que j'ai testé, cela fonctionne très bien, et je peux utiliser setDefaultEditor et ainsi de suite. Vous pouvez remarquer qu'il est possible d'améliorer ce comportement pour l'appliquer uniquement aux colonnes souhaitées.

public class JXMultiTypeColumnTable extends JXTable { 

private Map<Integer, Class<?>> viewedClassByColumn = new HashMap<Integer, Class<?>>(); 

public JXMultiTypeColumnTable(Object[][] rowData, Object[] columnNames) { 
    super(rowData, columnNames); 
} 

public JXMultiTypeColumnTable(int numRows, int numColumns) { 
    super(numRows, numColumns); 
} 

public JXMultiTypeColumnTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) { 
    super(dm, cm, sm); 
} 

public JXMultiTypeColumnTable(TableModel dm, TableColumnModel cm) { 
    super(dm, cm); 
} 

public JXMultiTypeColumnTable(TableModel dm) { 
    super(dm); 
} 

public JXMultiTypeColumnTable() { 
} 

@Override 
public Class<?> getColumnClass(int column) { 
    Class<?> recordedClass = this.viewedClassByColumn.get(column); 
    if (recordedClass != null) { 
     return recordedClass; 
    } 
    return super.getColumnClass(column); 
} 

private void recordViewedClass(int row, int column) { 
    this.viewedClassByColumn.put(column, 
      this.getModel().getValueAt(
      this.convertRowIndexToModel(row), this.convertColumnIndexToModel(column)) 
      .getClass()); 
} 

@Override 
public TableCellRenderer getCellRenderer(int row, int column) { 
    this.recordViewedClass(row, column); 
    return super.getCellRenderer(row, column); 
} 

@Override 
public TableCellEditor getCellEditor(int row, int column) { 
    this.recordViewedClass(row, column); 
    return super.getCellEditor(row, column); 
} 

}

N.B. Il est possible d'étendre JTable au lieu de JXTable.

Questions connexes