Java 基于列 class 的摆动单元格渲染器

Java swing cell renderer based on column class

在 Java Swing 中,我们有一个 JTableTableModelColumnModel 和一个 TableCellRenderer,它们一起工作以显示 table .

我如何提供自定义以获取基于列的自定义单元格渲染器 class - 而不是根据列索引设置渲染器。

final JTable table = new JTable(model);
table.getColumnModel().getColumn(0).setCellRenderer(new DateTimeRenderer());
table.getColumnModel().getColumn(1).setCellRenderer(new SuperDuperDoubleCellRenderer());

假设我有 20 个数字单元格!!!

上面的方法可行,但我不太喜欢该解决方案,因为它会在模型​​更改时更改 - 所以它没有很好地封装到那种程度 - 这是客户端代码。

TableModel 了解底层的 table 数据结构,它可以在其中进行到复杂类型的自定义映射(与 DefaultTableModel 和 Vectors 相对)- 它知道每个数据类型的数据类型列。

public class DemoTableModel implements TableModel {
    @Override
    public Class<?> getColumnClass(int columnIndex) {
        // date time, double, etc...
        return columnInfo.get(columnIndex).getDataType();
    }
}

我想做的是告诉 JTable,嘿,class 列(从 table 模型返回)是自定义 DateTime 类型 - 使用 CustomDateTimeCellRenderer。如果是双精度,则使用自定义 SuperDuperDoubleCellRenderer.

问题在于挖掘源代码以查看此行为在哪里结婚。

您可以在 CellRenderer 级别执行此操作 - 单元格渲染器只需要实现

Component getTableCellRendererComponent​(JTable table,
                                    Object value,
                                    boolean isSelected,
                                    boolean hasFocus,
                                    int row,
                                    int column)

没有什么可以阻止您告诉整个 JTable 使用 SmartCellRenderer 来呈现单元格,它查看 passed-in 值的类型并将实际呈现委托给 DoubleCellRenderer ,一个 StringCellRenderer,或者一个 CuteInternetCatRenderer。假设对象类型是唯一的,这应该很容易做到(如果由于 if (value instanceof InternetCat) { ... } 的集合决定如何根据其 class 呈现每个对象而有些丑陋)。

更好的解决方案(不需要难看的 instanceofs)是在列插入时将特定的渲染器分配给特定的列:

 // model index 0, width 75, renderer to use, editor to use
 myTable.getColumnModel().addColumn(0, 75, cuteInternetCatRenderer, null);

What I would like to do is to tell a JTable, hey the column class (returned from the table model) is a custom DateTime type - use the CustomDateTimeCellRenderer. If it is a double, then use the custom SuperDuperDoubleCellRenderer.

您通过指定 class 和渲染器将渲染器设置在 table 级别:

table.setDefaultRenderer(Double.class, yourDoubleCellRenderer);
table.setDefaultRenderer(CustomDateTime.class, yourCustomDateTimeRenderer);