Swing组件中的渲染器Renderer
创始人
2024-04-16 11:51:52
0

Swing组件根据其所操作的数据类型分为两种。标量数据类型的组件操作的是基本类型的数据,如字符串、布尔、数字等,此类型组件包括JTextField、JCheckBox、JLabel、JButton等。复合数据类型的组件操作的是诸如向量、矩形和非线形等类型的数据。向量数据类型的组件有JComboBox、JList,矩形数据类型的组件有JTable,非线形数据类型的组件如 JTree。

为更形象地展现各种类型的数据,复合数据类型的组件往往采用标量数据类型组件来表现每种数据元素。比如JTable的某一列数据是字符串类型,那么该列的单元格往往用JLabel方式展现每个字符串;如果一列数据是布尔类型,那么该列的单元格往往用JCheckBox方式展现每个布尔值。

如何实现复合数据类型的组件的渲染呢?最直接的是在paint方法中一个一个地根据数据类型画出每一个组件,但这种方法很显然代码复用率很低,大量重复了相应标量型组件的代码,代码的维护和同步会非常困难,也不容易实现皮肤切换。

为解决此问题,Swing体系中提出了所谓渲染器Renderer的概念,其核心思想是使用接口,封装和复用已有标量型组件的渲染代码,降低代码重复率,提高组件的可扩展性。

如何使用渲染器返回的组件渲染当前的单元格呢?JTable在自己内部隐藏了一个所谓的CellRendererPane组件,该组件是一个“零实现”的容器组件。虽然被添加到JTable上,但它是不可见的,其paint和update方法都为空,仅仅作为临时容纳渲染组件的容器,目的是将渲染组件粘合到JTable组件树上,使得渲染组件有效化,以便使它们达到渲染前的正确状态。下面代码演示了CellRendererPane的概要结构:

  1. public class CellRendererPane extends Container implements Accessible  
  2. {  
  3. //构造函数  
  4. public CellRendererPane() {  
  5. super();  
  6. //注意CellRendererPane的布局管理器为空,后面渲染时有用!  
  7. setLayout(null);  
  8. //不可见,使之不被显示在JTable上  
  9. setVisible(false);  
  10. }  
  11. //零实现  
  12. public void invalidate() { }  
  13. //零实现  
  14. public void paint(Graphics g) { }  
  15. //零实现  
  16. public void update(Graphics g) { }  
  17. ......  
  18. //下面是CellRendererPane的paintComponent方法:  
  19. public void paintComponent(Graphics g, Component c, Container p,
     int x, int y, int w, int h, boolean shouldValidate) {  
  20. ......  
  21. if (c.getParent() != this) {  
  22. //如果渲染组件c还没有添加当前CellRendererPane中  
  23. //添加进去  
  24. this.add(c);  
  25. }  
  26.  
  27. c.setBounds(x, y, w, h);  
  28.  
  29. if(shouldValidate) {  
  30. c.validate();  
  31. }  
  32. //下面主要处理双缓冲问题,可略去  
  33. ......  
  34. //准备图形对象  
  35. Graphics cg = g.create(x, y, w, h);  
  36. try {  
  37.  
  38. c.paint(cg);  
  39. }  
  40. }  
  41. }  

渲染器Renderer的核心思想都体现在上面红色代码标注的部分。将JTable的图形对象传递给组件的paint的方法,产生的结果是将组件画到了JTable上。其实Swing打印的原理也大抵如此,只不过这儿的图形对象变成了打印机的图形对象。虽然大部分Swing组件都专门对打印进行了专门的处理(主要是因为有一些图形元素不希望被打印的,比如填充的内容往往不希望打印,可能是太耗墨了),但基本过程是一样的。

渲染器的思想很像是摄像机、镜子等成像原理。作个比喻,如果你想获取某人的图像,一种方法是将此人一点点用笔画出来。另种方法是通过光线将此人照到镜子里或用照相机拍摄下来。其好处是不管是什么物体,都可以映射出来,具有很强的可扩展性。比如JTable中,表格中不仅可以使用JLabel、 JCheckBox、JComboBox等简单组件作为渲染器,而且可以使用其它任何的Swing组件进行渲染,包括复杂的组件JTable(比如实现表格套表的风格)、自定义的组件,渲染器方法带来的好处不仅仅是组件代码的复用,更带来了无限的可扩展性!

渲染器思想在Swing中有着广泛的应用。除利用它们实现JTable、JList、JTree和JComboBox等标准组件,还可以实现界面设计工具中属性页、类似UML设计图、类似于MS Excel风格的电子表格等更为复杂的界面组件,甚至IDE中常见的界面设计工具也是利用了渲染器的思想,它把整个组件树当作一个大渲染器,渲染出当前图形用户界面的设计效果。

渲染器是Swing展现复杂数据结构的利器。但是Swing组件不仅仅被用作展现数据,通常还是编辑数据的地方。实际上纯粹展现数据的Swing组件很少,标准组件中也许只有JLabel。复合数据类型的组件往往使用渲染器原理实现组件的渲染,使用所谓in-place editor实现组件的编辑。渲染器Renderer和Editor的结合赋予了Swing强大的灵活性,JTable、等组件这两种原理结合的代表。后续文章将讲述in-place editor在Swing中的使用。

【编辑推荐】

  1. 介绍Swing线程相关处理
  2. 浅析Swing客户端知识
  3. Swing线程解决方案
  4. 全面比较AWT和Swing
  5. 概述JSci.swing包的核心

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...