自定义swing组件 - 将节点转换为文本

时间:2008-10-18 14:01:43

标签: java swing

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

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

  • 将节点本身(作为Object)传递给渲染器,让渲染器决定如何显示它。
    • 这就是JList的做法。
    • 只需要更改文本即可使用自定义渲染器。
    • 允许显示节点的灵活性(甚至不必是文本)。
  • 将节点本身(作为Object)传递给渲染器,但在组件类中有一个convertValueToText()方法。
    • 这就是JTree的做法。
    • 渲染器可以像以前一样灵活 - 不要 使用此方法。
    • 必须覆盖组件才能更改文本转换。
  • 如上所述,但将convertValueTotext()委托给模型。
    • JXTable就是这样做的。
    • 该模型可能是此方法的最佳位置 - 并且更容易覆盖它。

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

任何人都可以对这个经常被忽视的Swing部分有所了解吗?

我最终做的是:

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

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

我对它很满意 - 它“感觉”正确,它有效,并且易于使用。

感谢您的观点!

3 个答案:

答案 0 :(得分:1)

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

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

然而,实用主义说这可能难以记住和维护。因此,在您的情况下,我建议:考虑一下您是否有可能从模型中提取非文本数据。如果不太可能,那么在模型中放入convertValueToText的等价物。

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

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

答案 1 :(得分:0)

AFAIK既没有JList也没有JTree要求渲染器渲染文本。渲染器将​​传递数据对象并返回一个JComponent,该JComponent在Tree / List中作为子项定位,然后呈现。
我愿意这样做。文本渲染器只返回JLabel。如果您希望能够改变方式,那么构造的文本将通过Formatter传递给TextRender,您就完成了。

  • 斯蒂芬

答案 2 :(得分:0)

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