【问题标题】:Difficulties understanding the renderers mechanism of swing's JTable and JTree难以理解swing的JTable和JTree的渲染器机制
【发布时间】:2012-11-20 07:30:06
【问题描述】:

通常在使用JTableJTree 时,用户会定义自己的单元格渲染器。

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

一切都很好。

我的问题是怎么可能?

该方法每次被表调用时,都会被赋予不同的参数,并且输出标签会随着这些参数的变化而变化。如果它确实是标签的同一个实例——不应该根据最后一次调用这个方法来改变它吗? 这不是说表格的所有单元格都被感染了由相同的标签实例组成,它拥有相同的值(最后一次调用渲染器方法的值)?

我已经搜索了网络,并在 Swing 的代码中进行了挖掘,但找不到任何实际复制输出标签的 clonecopy constructor 行为。 我找不到任何证据表明(可能)swing 使用反射来每次从头开始重新实例化渲染器。

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

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

他们暗示,我所说的确实是正确的,但没有解释它是如何实现的。

我听不懂。你们中的任何一个都可以吗?

【问题讨论】:

    标签: java swing jtable jtree renderer


    【解决方案1】:

    这是flyweight pattern 的实现。

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

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

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

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

    【讨论】:

    • +1 截图比喻很好。我认为最常用的是“邮票”,但截图可能更清晰
    • 谢谢。这个比喻确实起到了作用:)。现在明白了。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      经过一番挖掘,从DefaultTableCellRenderer documentation找到了下一个实现笔记:

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

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

      感谢(快速)回答

      【讨论】:

      • CellRendererPane 中可以找到类似的优化,由TableUI 代表使用并说明here
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-19
      相关资源
      最近更新 更多