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

Java 自定义swing组件-将节点转换为文本,java,swing,Java,Swing,我正在编写一个定制的swing组件(一些全新的东西,但想想JTree或JList)。我试图遵循JTree、JTable、JList等的一般设计以实现一致性(我还看到各种糟糕的第三方组件放弃了可分离模型和/或渲染器方法) 因此,我有一个充满节点、组件本身和渲染器的模型。在某些情况下,节点必须转换为文本并由渲染器显示。我不清楚最好的方法: 将节点本身(作为对象)传递给渲染器,并让渲染器决定如何显示它。 JList就是这样做的 只需自定义渲染器即可更改文本 允许在如何显示节点方面具有极大的灵活性(

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

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

  • 将节点本身(作为对象)传递给渲染器,并让渲染器决定如何显示它。
    • JList就是这样做的
    • 只需自定义渲染器即可更改文本
    • 允许在如何显示节点方面具有极大的灵活性(甚至不必是文本)
  • 将节点本身(作为对象)传递给渲染器,但在组件类中有一个convertValueToText()方法。
    • JTree就是这样做的
    • 渲染器可以像以前一样灵活-不必使用这种方法
    • 必须重写组件才能更改文本转换
  • 如上所述,但将convertValueTotext()委托给模型。
    • JXTable就是这样做的
    • 该模型可能是该方法的最佳位置,并且更容易在那里重写
我不想仅仅为了更改文本就必须自定义渲染器,但我希望能够自定义渲染器,使其不仅仅显示模型显示的字符串(否则为什么要使用渲染器)。我真的不喜欢JXTable使用反射在模型中查找convertValueToText(),这对我来说有点不好的魔力

有人能解释一下秋千这个经常被忽视的部分吗

解决方案

我最后做的是:

  • 向模型添加一个方法,该方法返回给定节点的字符串。重要的是,该值可以为null,表示渲染器应该知道该做什么,或者我们根本无法提供任何有用的内容
  • 组件具有相同的方法,并将调用传递给模型。这对于视图模型分离很重要。渲染器调用此方法,因此它不会直接与模型对话
  • 默认呈现程序调用上述方法,如果该方法不为null,则使用该方法,否则可以调用该值上的toString,或者提供默认值,或者其他任何方法
这让开发人员可以选择何时覆盖显示的值 -使用非null返回值重写该方法,知道默认呈现程序将显示此文本。 -提供一个自定义的渲染器,该渲染器传递给实际的节点对象,以便它可以在需要时执行“聪明”的操作

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


谢谢你的观点

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

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

然而,实用主义者说,这可能太难记住和保持。因此,在您的情况下,我建议:考虑一下您希望从模型中提取非文本数据的可能性有多大。如果不太可能,则在模型中放入等效的convertValueToText

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


这允许最大的灵活性,并可能使API的用户感到最自然。我相信这就是JTable模型,尽管我很久没有使用Swing了。

AFAIK JList和JTree都不需要渲染器来渲染文本。渲染器传递数据对象并返回一个JComponent,该JComponent在树/列表本身中定位为子元素,然后进行渲染。
我同意这个。文本的渲染器只返回一个JLabel。如果您希望能够更改方式,则构建文本并将格式化程序传递给TextRender,就完成了

  • 斯蒂芬

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

对不起,我的示例中的convertvalueToText()适用于JTree,而不是JTable(oops)。JTable的默认呈现程序似乎只是调用value.toString()。我接受了这一点,因为我认为这与我最终的操作非常接近-请参阅更新问题。将格式化程序传递给TextRenderer是什么意思?什么是TextRenderer?TextRenderer:渲染器接口的一个简单实现,它返回一个JComponent(例如JLabel),该组件将数据对象显示/呈现为字符串/文本传递给格式化程序:渲染可能采用(格式)[作为构造函数参数,格式化程序是一个好主意,但您仍然需要传入一个自定义渲染器实例(尽管只是带有新格式化程序的标准渲染器的实例)。我宁愿他们在大多数情况下只需要自定义模型