Sure, here’s the translation: 基于列类的Java Swing单元格渲染器

huangapple go评论70阅读模式
英文:

Java swing cell renderer based on column class

问题

在Java Swing中,我们有一个JTableTableModelColumnModel和一个TableCellRenderer,它们共同工作以显示表格。

如何实现自定义,以基于列类获取自定义单元格渲染器 - 而不是基于列索引设置渲染器。

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

假设我在表格中有20个数值单元格!!!

上述方法是有效的,但我对这种解决方案不是太热衷,因为当模型发生变化时,它会改变 - 所以封装性不够好 - 这是客户端代码。

TableModel了解底层的表格数据结构,可以执行自定义映射到复杂类型(而不是DefaultTableModel和Vectors)的操作,在这种情况下,它知道每列的数据类型。

public class DemoTableModel implements TableModel {
    @Override
    public Class<?> getColumnClass(int columnIndex) {
        // 日期时间,双精度等...
        return columnInfo.get(columnIndex).getDataType();
    }
}

我想做的是告诉JTable,嘿,列类(从表格模型返回)是一个自定义的DateTime类型 - 使用CustomDateTimeCellRenderer。如果是双精度,那么使用自定义的SuperDuperDoubleCellRenderer

问题是要查看源代码,以了解这种行为在哪里匹配。

英文:

In Java Swing we have a JTable, TableModel, ColumnModel and a TableCellRenderer which work together to display a table.

How can I provide customisation to get a custom cell renderer based on a column class - as opposed to setting the renderer based on column index.

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

Suppose I have 20 numeric cells in there!!!

The above works, but I am not so keen on that solution as it would change when the model changed - so it isn't well encapsulated to that extent - this is client code.

The TableModel understands the underlying table data structure where it can do the custom mapping to a complex type (as opposed to DefaultTableModel and Vectors) - where it knows the data types of how each column.

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

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.

The trouble is digging through the sources to see where this behaviour marries up.

答案1

得分: 3

> 我想要做的是告诉一个 JTable,嘿,这个列的类(从表格模型返回)是一个自定义的 DateTime 类型 - 使用 CustomDateTimeCellRenderer。如果是一个 double 类型,那么使用自定义的 SuperDuperDoubleCellRenderer。

你可以在表格级别上设置渲染器,通过指定类和渲染器:

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

> 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.

You set the renderer at the table level by specifying the class and renderer:

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

答案2

得分: 0

你可以在 CellRenderer 层面上进行操作 - 单元格渲染器只需要实现:

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

没有任何限制阻止你让整个 JTable 使用例如 SmartCellRenderer 这样的渲染器,它根据传入值的类型来委派实际的渲染工作给 DoubleCellRendererStringCellRenderer 或者 CuteInternetCatRenderer。假设对象类型是唯一的,这应该是很容易实现的(尽管有一些 if (value instanceof InternetCat) { ... } 这样的判断语句,根据对象的类来决定如何进行渲染,可能会让代码变得有些难看)。

一个更好的解决方案(无需使用丑陋的 instanceof)是在插入列时为特定列分配特定的渲染器:

// 模型索引为 0,宽度为 75,使用的渲染器,使用的编辑器
myTable.getColumnModel().addColumn(0, 75, cuteInternetCatRenderer, null);
英文:

You can do this at the CellRenderer level - cell renderers are only required to implement

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

Nothing stops you from telling the whole JTable to render cells using a, say, SmartCellRenderer that looks at the type of the passed-in value and delegates actual rendering to a DoubleCellRenderer, a StringCellRenderer, or a CuteInternetCatRenderer. Assuming object types are unique, this should be easy to do (if somewhat ugly because of the set of if (value instanceof InternetCat) { ... } that decides how to render each object based on its class).

A better solution (no ugly instanceofs required) is to assign specific renderers to specific columns at column insertion time:

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

huangapple
  • 本文由 发表于 2020年10月9日 16:42:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/64276674.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定