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

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

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

这一切都运作良好。

我的问题是它怎么样?

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

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

我已经阅读了关于JTables的Swing 教程,在那里我可以找到下一行:

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

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

我无法得到它。 可以吗?

这是flyweight模式的一个实现。

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

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

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

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

为了让JB明确解释 JTableJTree如何使用flyweight模式 ,请注意两个类如何提供公共方法getCellRenderer()getCellEditor() 。 检查这些方法,以查看JTable如何使用类文字作为运行时类型标记来按类选择渲染器或编辑器(如果列未指定)。 在内部, JTable使用Hashtable defaultRenderersByColumnClass作为实例存储。

经过一番挖掘后,从DefaultTableCellRenderer文档中找到了下一个实现说明:

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

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

谢谢(快速)答案