难以理解swing的JTable和JTree的渲染器机制

时间:2012-12-02 19:36:25

标签: java swing jtable jtree renderer

通常,当使用JTableJTree用户写入并分配时,它是自己的特定单元格渲染器。

DefaultTableCellRenderer继承用户的组件非常常见,并实现了渲染器方法getTableCellRendererComponent。事实证明,DefaultTableCellRenderer实际上是从JLabel继承的,因此当调用super(在render方法中)时返回自己(this),因此用户的渲染器也可以类似地返回自己(this)。

这一切都运作良好。

我的问题是它怎么样?

每次表调用此方法时,都会给出不同的参数,并根据这些参数更改输出标签。如果它确实是标签的同一实例 - 不应该根据最后一次调用此方法进行更改? 是不是意味着所有表格的单元格都是由同一个标签实例组成的,该标签实例保持相同的值(最后一次调用渲染器方法的值)?

我在网上搜索过,并在Swing的代码中挖掘,找不到任何实际重复输出标签的 clone 复制构造函数的行为。 我找不到任何证据表明(可能)swing使用反射,以便每次从头开始重新实例化渲染器。

我已经阅读了Swing的tutorial on JTables,在那里我可以找到下一行:

  

您可能希望表中的每个单元格都是一个组件。但是,出于性能原因,Swing表的实现方式不同。   相反,单个单元格渲染器通常用于绘制包含相同类型数据的所有单元格。您可以将渲染器视为可配置的墨迹标记,该表用于将适当格式化的数据标记到每个单元格上。当用户开始编辑单元格的数据时,单元格编辑器会接管单元格,控制单元格的编辑行为。

他们给出了一个暗示,我所说的确实是正确的,但不解释它是如何实现的。

我无法得到它。可以吗?

3 个答案:

答案 0 :(得分:11)

这是flyweight pattern的实现。

当JTable重新绘制自身时,它会启动一个循环并遍历每个必须绘制的单元格。

对于每个单元格,它使用与单元格对应的参数调用渲染器。渲染器返回一个组件。此组件绘制在与当前表格单元格对应的矩形中。

然后为下一个单元格调用渲染器,并且返回的组件(例如,具有不同的文本和颜色)被绘制在与单元格对应的矩形中。

想象一下,每次调用渲染器时,都会获取返回组件的屏幕截图并将其粘贴到表格单元格中。

答案 1 :(得分:4)

对于@ JB明确explication JTableJTree如何使用flyweight pattern,请注意两个类如何提供公共方法getCellRenderer()和{{ 1}}。检查这些方法,看看getCellEditor()如何使用Class Literals as Runtime-Type Tokens按类选择渲染器或编辑器(如果列没有指定)。在内部,JTable使用JTable作为实例存储。

答案 2 :(得分:3)

经过一番挖掘,找到了DefaultTableCellRenderer documentation的下一个实施说明:

实现注意:此类继承自标准组件类JLabel。然而,JTable采用独特的机制来渲染其单元格,因此需要从其单元格渲染器中稍微修改一些行为。表类定义单个单元格渲染器,并将其用作橡皮图章,用于渲染表格中的所有单元格;它渲染第一个单元格,更改该单元格渲染器的内容,将原点移动到新位置,重新绘制它,依此类推。标准JLabel组件并非设计为以这种方式使用,我们希望避免每次绘制单元格时触发重新验证。这会大大降低性能,因为重新验证消息将在容器的层次结构中向上传递,以确定是否会影响任何其他组件。由于渲染器仅在绘制操作的生命周期中具有父级,因此我们同样希望避免与绘制操作的层次结构相关联的开销。因此,此类会将validate,invalidate,revalidate,repaint和firePropertyChange方法重写为no-ops,并仅覆盖isOpaque方法以提高性能。如果您编写自己的渲染器,请记住这一性能考虑因素。

这基本上是JB在上面解释的内容。

感谢(快速)答案