3

我正在编写一个自定义摆动组件(全新的东西,但想想 JTree 或 JList)。我正在尝试遵循 JTree、JTable、JList 等的总体设计以保持一致性(我还看到各种糟糕的第 3 方组件放弃了可分离模型和/或渲染器方法)。

所以,我有一个充满节点的模型、组件本身和一个渲染器。在某些时候,必须将节点转换为文本并由渲染器显示。我不清楚最好的方法:

  • 将节点本身(作为对象)传递给渲染器,让渲染器决定如何显示它。
    • 这就是 JList 的做法。
    • 需要一个定制的渲染器来改变文本。
    • 在如何显示节点方面具有很大的灵活性(甚至不必是文本)。
  • 将节点本身(作为对象)传递给渲染器,但在组件类中有一个 convertValueToText() 方法。
    • 这就是 JTree 的工作方式。
    • 渲染器可以像以前一样灵活——不必使用这种方法。
    • 必须重写组件才能更改文本转换。
  • 如上所述,但将 convertValueTotext() 委托给模型。
    • 这就是 JXTable 的工作方式。
    • 该模型可能是这种方法的最佳位置 - 并且在那里更容易覆盖。

我不想仅仅为了更改文本而自定义渲染器,但我希望能够自定义渲染器来做的不仅仅是显示模型显示的字符串(否则为什么要使用渲染器)。我真的不喜欢 JXTable 使用反射在模型中查找 convertValueToText() 的事实——这对我来说是一种不好的魔法。

谁能解释一下 Swing 这个经常被忽视的部分?

解决方案

我最终做的是:

  • 向模型添加一个方法,该方法返回给定节点的字符串。重要的是,这可以为 null 以指示渲染器应该知道该做什么,或者我们根本无法提供任何有用的东西。
  • 该组件具有相同的方法,并将调用传递给模型。这对于视图模型分离很重要。渲染器调用此方法,因此它不直接与模型对话。
  • 默认渲染器调用上述方法,如果它不为空,则使用它,否则它可以在值上调用 toString,或提供默认值,或其他。

这让开发人员在他们想要覆盖显示的值时有一个选择 - 使用非空返回值覆盖该方法,因为他们知道默认渲染器将显示此文本。- 提供一个自定义渲染器,它传递实际的节点对象,以便它可以在需要时做“聪明”的事情。

我对它很满意——它“感觉”不错,它有效,而且易于使用。

感谢您的观点!

4

3 回答 3

1

好问题。这不是 Swing 特有的,而是关于模型和视图之间差异的哲学问题。

一般来说,将对象转换为文本是模型的工作还是视图的工作?我的纯粹主义者说,实际上你想要一个视图层次结构——一个将对象模型转换为文本,一个用于显示文本。您甚至可能需要两个以上的 - 例如,对象到文本、文本到文档结构、文档结构到 HTML,然后是 CSS 来呈现给用户。

然而,实用主义认为这可能很难记住和维护。因此,在您的情况下,我建议:考虑一下您想要从模型中提取非文本数据的可能性有多大。如果不太可能,则将等价的 convertValueToText 放入模型中。

否则,允许组件使用渲染器(如果给定了渲染器),或者获取对象值并在内部将其转换为文本。

这允许最大的灵活性,并且可能使 API 的用户感觉最自然。我相信这是 JTable 模型,虽然我很长时间没有使用 Swing。

于 2008-10-18T14:52:40.907 回答
0

AFAIK JList 和 JTree 都不需要渲染器来渲染文本。渲染器传递数据对象并返回一个 JComponent,该 JComponent 在 Tree/List 本身中定位为子对象,然后渲染。
我会选择这个。文本渲染器只会返回一个 JLabel。如果您希望能够更改方式,则构造文本并将 Formatter 传递给 TextRender,然后您就完成了。

  • 斯蒂芬
于 2008-10-18T22:00:58.107 回答
0

如果您必须编写自己的组件,请尽可能简单。在很多情况下,如果您需要自定义渲染器,那么您并不关心组件或模型的解释。模型保存您的数据。在这种情况下也是自定义编写的。从我的角度来看,好的选择是基于第一个选项。提供实现 AbstractRenderer 的 DefaultRenderer 并在其中添加所有方法,如 toText(Object o) 等。然后让我决定是要使用默认功能还是更喜欢自己编写。你真的需要自定义组件吗?为了使其正常工作,需要做很多工作。这个组件值得这一切吗?

于 2008-10-19T18:46:28.737 回答