技术开发 频道

智能数据使 Swing 保持简单

        iDisplay 结构是根据 iData 来创建定制显示的层。例如,可以考虑这样一个接口:其中,首选的 Manufacturer 应该用红色文本显示以提示用户其首选状态。通常,这需要复杂的逻辑来检索不是由渲染器传入的数据值,这会导致复杂的代码,使得以数据为中心的定制显示的实现变得不切实际。iDisplay 同 iData 的紧密集成使得这一方案非常简单,这样做也为扩展创建了一个集中的位置。

  只读智能数据的显示间接层(ImmutableIDisplay)

  ImmutableIDisplay 封装了特定于显示的逻辑。可以通过 ImmutableIDisplay 让对于三种主要渲染器类型每一个有 get[Component]CellRendererComponent() 方法来实现这一点,这三种类型是: TableCellRenderer 、 TreeCellRenderer 和 ListCellRenderer 。通过包含 ImmutableIDisplay , ImmutableIDisplayIData 将 ImmutableIDisplay 与 ImmutableIData 集成在一起。

  当 JTable 调用 UniversalTableCellRenderer 中的 getCellRendererComponent() 并传入一个 ImmutableIDisplayIData 类型的对象时, UniversalTableCellRenderer 则转发 getCellRendererComponent 请求给相应的 get[Component]CellRendererComponent , get[Component]CellRendererComponent 位于 ImmutableIDisplayIData 所包含的 ImmutableIDisplay 中。

  让我们看一看“自行车商店”演示的另外一个示例,其中用户输入一个低于 cost 的 price ,随后 price 和 cost 单元的背景颜色变红。 ImmutableIDisplay 的 getTableCellRenderer() 方法检索 DataObject ,并检查 price 是否低于 cost 。如果是这样,就将背景设置为红色;否则就将背景设置为白色。当没有出现特例时,记住将背景显式地设置成缺省颜色,这一点很重要。Swing 使用最轻量级的模式用于渲染,重复地绘制同一个组件。如果更改了特例的标准设置而又没有为标准情况复位,那么就会产生难以预料的结果。

  清单 11. Bicycle 成本的 getTableCellRenderer()方法根据数据对单元着色

1 public TableCellRenderer getTableCellRenderer(JTable table, Object value,
2   boolean isSelected, boolean hasFocus, int row, int column)
3 {
4       //cache old background for change comparisons
5       Color oldColor = renderer.getBackground();
6       //cache old background for change comparisons
7       Color newColor = null;
8       //check to see if Object is a MutableIData
9       if (value instanceof MutableIData)
10       {
11         MutableIData arg = (MutableIData)value;  //cast it.
12         Bicycle bike = (Bicycle)arg.getSource();
13         if (arg.getData() instanceof Number)  //check the data type
14         {
15         // retrieve price and cost from the DataObject
16           double cost = ((Number)arg.getData()).doubleValue();
17           double price = bike.getPrice();
18           //make comparisons
19           if (price > cost)
20             newColor = Color.cyan;
21           else
22             newColor = Color.red;
23         }
24       }
25       // check and see if color changed
26       if (!newColor.equals(oldColor))
27           this.setBackground(newColor);
28 }
29

  图 7. 带有 price 和 cost 背景颜色验证的表

        

  可编辑智能数据的显示间接层(MutableIDisplay)

  对于 iDisplay 实现,也存在不可修改/可修改的差异。 MutableIDisplay 负责编辑器,而 ImmutableIDisplay 负责渲染器。就象 ImmutableIDisplayIData 一样,有一个继承 MutableIData 且含有一个 MutableIDisplay 的 MutableIDisplayIData 。其用法同 ImmutableIDisplay 的用法相同,不同之处只是它实现的是 get[Component]CellEditor() 方法而不是 get[Component]CellRenderer() 方法。工具箱包含 JTable、JTree 和 JComboBox 的定制编辑器。

  将 get[Component]CellRenderer() 和 get[Component]CellEditor() 方法转发到 iDisplay 创建了一个有用的间接层。主要结果是产生了一个定制显示设置和功能的集中的、已封装的位置。iData 使用 iDisplay 的内涵而不是扩展,这样,除了限制了类的数目之外还增加了灵活性和可扩展性。最为重要的是,几乎不需要定制编辑器和渲染器,它们通常包含非常复杂的显示逻辑。虽然需要完整的定制编辑器和渲染器,但是可以使用由 iDisplay 提供的间接层来实现大多数显示。

  缺陷

  在实现 iData 技术时,需要记住有几个缺陷:

  性能:对于大多数应用程序来说,iData 技术并没有带来显著的性能开销。该技术规定了大量的间接而不是逻辑或处理。然而,如果 getData() / setData() 方法或 get[Component]CellRenderer() / Editor () 方法有太多逻辑,那么就会产生问题。每次绘制组件时,就会为组件中的每一个单元调用这些方法中的任何逻辑。因此,请尽可能地使这些方法保持简洁。

  添加到代码库中的类:毫无疑问,使用 iData 技术需要相当数量的类。任何面向对象的技术都会如此,而且这有一定好处。事实上,在这些额外的类中驻留着大量特定于应用程序的业务逻辑,这样会强制产生某个级别的封装,而这种封装在一般情况下是不会出现的。如果要使类的数量保持绝对最低,那么这可能不是非常好的选择。对于这些对规模要求至关重要的应用程序已经做了很多优化,然而通常有相关的性能代价。因此,当决定代码复杂性、类的数目以及性能代价时,应该考虑应用程序需求。

  学习曲线:这是最突出的缺陷。设计 iData 技术时,考虑的是灵活性和可扩展性。这就要求某些数量的抽象,这些抽象首先就容易令人迷惑,即便没有让人望而却步。我相信经过一些探索后,这一体系结构是可达到的,但是这确实需要坚持不懈。

  结束语

  使用结合 iData 间接层的智能数据来填充组件模型有助于创建用于实现高级用户界面功能的灵活和可扩展的集中位置。此外,可以使用完全封装的类中相对简单的逻辑来实现这一功能,这可以增加灵活性和重用。附加的开放源码工具箱使向集成 iData 技术的转换变得方便,这是因为已经编写并测试了转换所需的大多数代码。每个应用程序只需 iData 间接层的自己实现就可以成功地使用上面所讨论的技术。没有定制主要的 Swing 组件,没有定制模型,也没有更改标准 Swing 功能 ― 有的只是仔细放置的间接。结果是以直接、灵活并且可扩展的方式简化了复杂显示功能和定制实现的系统。

  开放源码说明

  我相信工具箱对于成功实现 iData 方法是至关重要的。工具箱除了提供一些优化和长期开发的助手类之外,还提供了经过用户测试的代码,从而使集成时间减至最少。设计和实现都要受所开发的项目的影响。显然,您可能碰到其需求可能更方便地通过对工具箱做一些修改来实现的项目,当开发人员帮助改进工具箱的设计时,将极大地增强其可用性,同时会创建更可访问和更健壮的实现。

  该工具箱是遵照 Artistic 许可证(Artistic License)通过 SourceForge.net 分发的。该项目主页包含完整的源代码、文档、二进制分发版以及到邮件列表服务器和其它信息的链接。鼓励您对代码做一些改进以便包含在未来的发行版中。根据开放源码协议的规定,可以自由使用所有应用程序。

0
相关文章