收藏 分享(赏)

Swing框架之Renderer.doc

上传人:HR专家 文档编号:7518841 上传时间:2019-05-20 格式:DOC 页数:18 大小:167KB
下载 相关 举报
Swing框架之Renderer.doc_第1页
第1页 / 共18页
Swing框架之Renderer.doc_第2页
第2页 / 共18页
Swing框架之Renderer.doc_第3页
第3页 / 共18页
Swing框架之Renderer.doc_第4页
第4页 / 共18页
Swing框架之Renderer.doc_第5页
第5页 / 共18页
点击查看更多>>
资源描述

1、Swing 框架之 RendererSwing 组件根据其所操作的数据类型分为两种,一种是标量数据类型的组件,一类是复合数据类型的组件。标量数据类型的组件操作的是基本类型的数据,如字符串、布尔、数字等,此类型组件包括 JTextField、JCheckBox、JLabel、JButton 等。复合数据类型的组件操作的是诸如向量、矩形和非线形等类型的数据。向量数据类型的组件有JComboBox、JList,矩形数据类型的组件有 JTable,非线形数据类型的组件如 JTree。为更形象地展现各种类型的数据,复合数据类型的组件往往采用标量数据类型组件来表现每种数据元素。比如 JTable 的某一列

2、数据是字符串类型,那么该列的单元格往往用JLabel 方式展现每个字符串;如果一列数据是布尔类型,那么该列的单元格往往用JCheckBox 方式展现每个布尔值。如何实现复合数据类型的组件的渲染呢?最直接的是在 paint 方法中一个一个地根据数据类型画出每一个组件,但这种方法很显然代码复用率很低,大量重复了相应标量型组件的代码,代码的维护和同步会非常困难,也不容易实现皮肤切换。为解决此问题,Swing 体系中提出了所谓渲染器(Renderer)的概念,其核心思想是使用接口,封装和复用已有标量型组件的渲染代码,降低代码重复率,提高组件的可扩展性。渲染器是如何工作的呢?我们以 JTable 的渲染

3、代码来演示渲染器的工作原理。下面代码是从 JTable 的 UI 类 javax.swing.plaf.basic.BasicTableUI 中摘出的部分代码(JDK 6):/注:为清晰期间,只显示了关键代码public void paint(Graphics g, JComponent c) /计算当前可显示区域的行列范围/ 画出表格的分割线paintGrid(g, rMin, rMax, cMin, cMax);/ 画出表格单元格的内容paintCells(g, rMin, rMax, cMin, cMax);/如果正在拖动列,画出正在被拖动的线paintDropLines(g);pain

4、tCells 实现所有单元格的渲染过程:private void paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax) for(int row = rMin; row c.setBounds(x, y, w, h);/将渲染组件在 JTable 的组件树上有效化,目的是如果渲染组件是一个有内部结构的复合组件,比如一个 JTextField 和一个 JButton 构成的一个复合框组件,该过程将会使内部组件进行布局,并递归此过程,使得该组件达到正常显示应该达到的效果。 if(shouldValidate) c.validat

5、e();/下面主要处理双缓冲问题,可略去/准备图形对象Graphics cg = g.create(x, y, w, h);try /调用渲染组件的重画方法渲染,注意由于 cg 其实是 JTable 的图形对象,因此其效果是将该组件渲染到 JTable 上相应单元格,从而达到了代码复用。 c.paint(cg);渲染器的核心思想都体现在上面红色代码标注的部分。将 JTable 的图形对象传递给组件的 paint 的方法,产生的结果是将组件画到了 JTable 上。其实 Swing 打印的原理也大抵如此,只不过这儿的图形对象变成了打印机的图形对象。虽然大部分 Swing 组件都专门对打印进行了专

6、门的处理(主要是因为有一些图形元素不希望被打印的,比如填充的内容往往不希望打印,可能是太耗墨了),但基本过程是一样的。渲染器的思想很像是摄像机、镜子等成像原理。作个比喻,如果你想获取某人的图像,一种方法是将此人一点点用笔画出来。另种方法是通过光线将此人照到镜子里或用照相机拍摄下来。其好处是不管是什么物体,都可以映射出来,具有很强的可扩展性。比如JTable 中,表格中不仅可以使用 JLabel、JCheckBox、JComboBox 等简单组件作为渲染器,而且可以使用其它任何的 Swing 组件进行渲染,包括复杂的组件 JTable(比如实现表格套表的风格)、自定义的组件(比如嵌入图片)。渲染

7、器方法带来的好处不仅仅是组件代码的复用,更带来了无限的可扩展性!渲染器思想在 Swing 中有着广泛的应用。除利用它们实现 JTable、JList、JTree 和JComboBox 等标准组件,还可以实现界面设计工具中属性页、类似 UML 设计图、类似于 MS Excel 风格的电子表格等更为复杂的界面组件,甚至 IDE 中常见的界面设计工具也是利用了渲染器的思想,它把整个组件树当作一个大渲染器,渲染出当前图形用户界面的设计效果。渲染器是 Swing 展现复杂数据结构的利器。但是 Swing 组件不仅仅被用作展现数据,通常还是编辑数据的地方。实际上纯粹展现数据的 Swing 组件很少,标准组

8、件中也许只有JLabel。复合数据类型的组件往往使用渲染器原理实现组件的渲染,使用所谓 in-place editor 实现组件的编辑。渲染器 Renderer 和 Editor 的结合赋予了 Swing 强大的灵活性,JTable、等组件这两种原理结合的代表。后续文章将讲述 in-place editor 在 Swing 中的使用。Swing 的 API 具有很强的灵活性和可扩展性,比如标准复合数据型组件一般不需要进行渲染器扩展,就可以实现许多应用,但是当遇到需要自定义扩展的需求时,Swing 的高度抽象灵活的 MVC 框架也可以优雅从容的完成。Swing 的这一特色典型的体现在其渲染器扩展

9、思想上。那么如何使用渲染器呢?如何自定义渲染器来扩展组件呢?如何将渲染器思想应用到自定义组件上呢?复合数据类型的组件如 JTable、JTree、JList 以及 JComboBox 都定义适合自己类型的渲染器接口,它们与渲染器接口之间的映射关系如下表所示:组件 渲染器JTable TableCellRendererJTree TreeCellRendererJList ListCellRendererJComboBox ListCellRendererTableCellRenderer 接口定义了 JTable 渲染器接口:public interface TableCellRenderer

10、 /*返回渲染表格的组件,使用该方法在渲染之前配置渲染器。*参数 table:请求渲染器渲染的表,可以为空。*参数 value:要渲染的单元格的值,由渲染器来决定如何解释和渲染该值。比如如果value 的值为字符串“true”,渲染器可以渲染成字符串,也可以渲染成一个 check box。该值可以为空。*参数 isSelected:当前表格是否被选中,渲染器应据此决定是否应该高亮显示。*参数 hasFocus:当前表格是否拥有焦点,渲染器应据此进行特殊渲染,比如画一个虚线框。*参数 row:当前表格的行号。如果渲染的是表头,该值为1。*参数 column:当前表格的列号。*/Component

11、 getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus,int row, int column);TreeCellRenderer 定义了 JTree 的渲染器接口。public interface TreeCellRenderer /*将树当前节点的值赋给 value,如果 isSelected 是 true,当前节点要被渲染成选中状态,如果 expanded 是 true,当前节点是处于打开状态,如果 leaf 是 true,当前代表的是一个叶子节点,如果

12、hasFocus 是 true,表示当前节点拥有焦点。tree 是需要渲染的树。改方法返回一渲染组件渲染当前树的节点。*/ Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus);ListCellRenderer 是 JList、JComboBox 的渲染器接口。public interface ListCellRenderer /* 返回一渲染组件显示列表中的某个选项

13、。参数 list 是正在渲染的列表,value 是列表中当前正在渲染的项,index 是当前正在渲染的项的索引,isSelected 是当前项是否选中,cellHasFocus 是指当前项是否拥有焦点。*/ Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus);如何使用这些渲染器接口来实现对这些组件的扩展呢?Jtable 中许多方法来实现渲染器的设置,比如方法:public void setDefaultRend

14、erer(Class columnClass, TableCellRenderer renderer);如果在 TableColumn 中没有设置渲染器的话,该方法设置对于数据类型 columnClass 应该使用的渲染器。也可以使用jTable.getColumnModel().getColumn(columnIndex).setCellRenderer(new MyTableCellRenderer()设置 columnIndex 列的渲染器。最直接的方法是继承 JTable,覆盖 public TableCellRenderer getCellRenderer(int row, int

15、column) 方法,返回任何位置的 TableCellRenderer。该方法使我们能轻易实现类似于 NetBeans 界面设计工具的属性表:在 CSDN 上有人问如何实现表套表,实际如果清楚了渲染器的工作原理可以很容易实现这个功能,下面是一个很短的代码,它实现了在表的 2,3 表格中插入一表:public class TableOfTable extends JTable public TableOfTable() /添加一个缺省 model,实际中可以根据自己需求定制。 setModel(new DefaultTableModel( ); /将第二行高度设置宽一些,使嵌入的表格显示起来好

16、看些。 setRowHeight(1,super.getRowHeight()*4); /重载getCellRenderer 提供自己的 TableCellRenderer public TableCellRenderer getCellRenderer(int row, int column) if(row = 1 /实现TableCellRenderer 的方法,提供该子表作为渲染器 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean h

17、asFocus, int row, int column) return subTable; ; else/如果是其他地方的表格,沿用父类中提供的渲染器 return super.getCellRenderer(row, column); 短短几行代码就可以实现如下图所示的界面:当然你可以根据需求具体定制更为复杂表格的实现,但大体原理就是这样的。Jtable、JList、JTree 以及 JComboBox 可以接受的渲染组件不仅仅可以是标准组件,也可以是自定义的组件。比如想实现如下所示的颜色选择器:图中的渲染器可以从基本的 BasicComboBoxRenderer 继承,它实际上是继承 J

18、Label 的一个类,你可以设置该 JLabel 的图标,让它显示当前的颜色。为了提供这样一个显示颜色的图标,可以实现这样一个 ColorIcon:public class ColorIcon implements Iconstatic final int BOX=10;private Color color;public ColorIcon(Color c)color=c;public void paintIcon(Component c, Graphics g, int x, int y) Color old = g.getColor();g.setColor(color);g.fillR

19、ect(x,y,BOX,BOX);g.setColor(Color.black);g.drawRect(x,y,BOX,BOX);g.setColor(old);public int getIconWidth() return BOX;public int getIconHeight() return BOX;然后自定义一个渲染器:public class ColorRenderer extends BasicComboBoxRenderer private JComboBox combo;public ColorRenderer(JComboBox cb) combo=cb;setFont(

20、combo.getFont();public Component getListCellRendererComponent(JList list,Object value,int index,boolean isSelected,boolean cellHasFocus) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);JLabel lbl=(JLabel)this;if(value!=null)Color c=(Color)value;lbl.setText(ColorIcon.

21、getColorName(c);lbl.setIcon(new ColorIcon(c);return this;最后,在程序中使用它:JcomboBox colorCombo=new JComboBox();colorCombo.setRenderer(new ColorRenderer(this);addItem(Color.red);addItem(Color.orange);其实,渲染器不仅仅可以用在标准组件 JTable、JList、JTree 和 JComboBox,也可以在自己定制的组件中使用渲染器的思想实现复杂的界面,比如 UML 图、工作流图、电路图,模拟 JTable 实现

22、类似于 MS Excel 的电子表格控件,甚至可以实现自己的用户界面设计工具。前面文章中曾经提到过的数据库设计插件和报表设计插件就是根据渲染器原理自定义出的组件。因此,熟悉了 Swing 的结构尤其是渲染器的思想,加上一些额外的知识,比如 double buffering、glass pane、robot、swing threading、color model、java2d 等等,可以做出许多事情来。人有多大胆,地有多大产。但深入学习和了解 Swing 的基本结构,这是前提。今天的文章主要是以实例演示了这些渲染器的应用,文中的例子只是演示作用,加深你对渲染器的印象。但是真正吃透渲染器的各种技术

23、,还需要自己深入的学习和实践。前面文章提到过,许多复合数据型组件不仅仅需要展现数据,还需要编辑数据。比如JTable 的某些单元格可能需要编辑,JComboBox 除了选择外还可以直接编辑数据,有些JTree 有时也需要直接编辑节点。Swing 中解决此类问题的方案叫做所谓的 in-place editor。Swing 综合 in-place editor 和 Renderer 原理赋予了 Swing 扩展复杂组件功能的能力。注意 in-place editor 其实只是普通的 Swing 组件,并不是新的 Swing 元素,它们往往结合 Renderer 完成组件的扩展,所以我把它们和 Re

24、nderer 放在一起讲了。Swing 可以使用 In-place editor 的两个前提条件是:1. Swing 组件需要能脱离容器组件独立存在;2. Swing 组件树能在运行时动态地被修改,包括添加和删除。Swing 组件树就像浏览器的 HTML DOM 树一样,可以通过脚本语言 JavaScript 进行动态修改,从而达到浏览器页面的局部更新的功能,Swing 通过动态的往容器组件中添加或者删除编辑组件实现复合类型组件的 in-place editor 功能。所有 Swing 组件都是直接或者间接继承自 JComponent,而 JComponent 是 Container类的一个子

25、类,因此所有的 Swing 组件都可看作一个容器组件。复合数据类型的组件也是如此,它们内部往往拥有自己的子结构、布局管理器、为实现某种功能而隐藏了的子组件(比如前篇文章中所提到的 CellRendererPane)等。复合数据类型的组件通过动态修改自己内部组件树结构实现 in-place editor。In-place editor 的生命周期包括激活、编辑、停止编辑、取消编辑、删除编辑器等。下面以 JTable 为例详细了解 In-place editor 的工作过程。首先要了解 JTable 的 in-place editor 接口 TableCellEditor 的定义:public i

26、nterface TableCellEditor extends CellEditor /*该方法返回 JTable 当前表格的编辑组件,该组件根据提供的参数table、 value、isSelected、row、column 进行配置。注意,对该组件的调用有可能会导致停止编辑,丢失尚未编辑完的数据。该组件将作为 JTable 的子组件添加到组件树上,之后就可以接受用户的输入了。*/Component getTableCellEditorComponent(JTable table, Object value,boolean isSelected,int row, int column);pu

27、blic interface CellEditor /*返回编辑器内的值,必须是编辑后有效的值,用在 JTable 中作为获取编辑结果用*/public Object getCellEditorValue();/*让编辑器判断 anEvent 是否能激活编辑动作,anEvent 使用的是 JTable 组件坐标系,这儿编辑器不能假设 getCellEditorComponent 返回的组件已经安装在 JTable 中。如果当前事件触发编辑行为,则返回 true,否则 false。*/public boolean isCellEditable(EventObject anEvent);/*该方法

28、同前一方法类似,只不过是判断该事件是否允许选中当前格。大多数情况下,这儿直接返回 true,因为一般如果可编辑,就应该允许被选中。然而有些情况下编辑行为发生时,并不想改变表格的选中状态。比如,用户可能想改变 checkbox 编辑器的值,却并不想因为要点击 checkbox 而改变 JTable 当前选中的其他行。*/public boolean shouldSelectCell(EventObject anEvent);/*停止编辑器的编辑,接受部分编辑的值作为编辑结果值。如果编辑不能停止,则返回false,这对于编辑器检查正在编辑的值是否有效,是否能接受无效值时很有效。 */public

29、boolean stopCellEditing();/*告诉编辑器取消编辑,不要使用任何部分编辑过的值*/public void cancelCellEditing();/*添加 CellEditorListener,当编辑器停止或者取消编辑行为时触发该处理器*/public void addCellEditorListener(CellEditorListener l);/*删除 CellEditorListener*/public void removeCellEditorListener(CellEditorListener l);再看一下 CellEditorListener 的定义:

30、public interface CellEditorListener extends java.util.EventListener /*通知编辑器已经停止编辑,编辑效果生效。*/public void editingStopped(ChangeEvent e);/*通知编辑器已经取消编辑,编辑效果被取消*/public void editingCanceled(ChangeEvent e);当鼠标双击之类引起编辑的事件发生时,JTable 的激活编辑器的过程可用下面的图来示意:首先检查当前是否正在编辑。如果正在编辑,则调用 TableCellEditor 的stopCellEditing

31、来结束编辑。stopCellEditing 如果不能正常结束,则返回 false,这时便把焦点重新定位给该编辑器,并结束。如果当前不是正在编辑,或者虽然正在编辑,但是 stopCellEditing 正常结束了,则判断当前的鼠标事件是否是鼠标拖动行为。如果是则调用 mousePressedDND 方法处理。否则说明该事件有可能引发编辑功能。接着调用TableModel.isCellEditable 判断该当前单元格是否允许编辑。如果允许编辑,则获得当前单元格的 TableCellEditor,调用其 isCellEditable 判断当前鼠标事件是否意味着激活编辑(比如规定双击意味着激活编辑、

32、单击并不激活等)。如果是激活编辑事件,则从TableCellEditor.getTableCellEditorComponent 获取编辑组件,最后将该组件添加到组件树上,添加适当的处理器、有效化之后等待用户输入。TableCellEditor 的 stopCellEditing 方法通常会删除当前编辑器。上面过程中,如果 JTable 正在处于编辑中,鼠标的点击则会导致调用 TableCellEditor 的stopCellEditing 方法删除编辑器,并开始新的编辑器的安装过程。stopCellEditing 在这个过程中获取编辑器的值并把它赋予 JTable。其工作过程如下:table

33、CellEditing 的 stopCellEditing(左边示意图)先检查目前编辑组件的值是否有效(比如输入的整数是否越界)。如无效则(有时需要提示用户)返回 false。如果有效则将该值作为 editor 的最终值存储起来,以备 JTable 通过editor.getCellEditorValue 调用。然后触发编辑停止事件 fireEditingStopped。由于JTable 在安装编辑器时,总把自己注册为它的 CellEditorListener 处理器,因此当JTable 能接到该通知。之后 JTable 就在其 editingStopped(右边示意图)方法中处理该事件。JTa

34、ble 首先使用 editor.getCellEditorValue 获得该 editor 编辑好的值,并调用setValueAt 将该值更新到当前单元格,最后调用 removeEditor 删除该编辑器。控制返回到 TableCellEditor 的 stopCellEditing(左边示意图图)后,stopCellEditing 返回 true结束整个过程。TableCellEditor 还会发出另一个事件 fireEditingCanceled。这经常出现在编辑器本身有所谓取消功能编辑组件上。比如想在按下 ESC 键时取消当前正在编辑的值,就可以调用 TableCellEditor 的

35、cancelEditing 来取消。cancelEditing 的工作过程比较简单,往往是直接通过 fireEditingCanceled 触发取消动作,侦听的 JTable 会在其editingCanceled 方法中简单将编辑器删除去,继续保留以前的值。理解 TableCellEditor 接口的方法之间的关系对于编写自己的 Editor 很重要,它们之间除了上面注释所描述的含义外,还有一些暗示的关系编写程序时需要注意:1.在自定义编辑器的 stopCellEditing 中要检查编辑组件正在编辑数据的有效性。如有效,要通过 fireEditingStopped 之类方法通知注册在此编辑器

36、上的接口。如果没有触发,JTable 将不能正常工作,编辑的值也会被丢失。最后要返回 true 作为成功的标识;如果数据没有效,一般做法是提示用户错误,用户确认错误提示后要要把焦点重新定位到编辑组件上,并返回 false 作为失败的标识。2.注意在 fireEditingStopped 调用之前,getCellEditorValue 返回的值一定要是当前有效的值。因为 JTable 会紧跟其后,调用该方法将编辑好的值填入表中并删除当前编辑器。3.cancelCellEditing 一般什么都不做,简单的 fireEditingCanceled 就行了。JTable 响应该事件仅仅是简单的删除编

37、辑器。4.要实现方法 addCellEditorListener 和 removeCellEditorListener,而不能空着它们,并且要定义 fireEditingStopped 和 fireEditingCanceled 两个方法以便在stopCellEditing 和 cancelCellEditing 方法中使用它们触发事件。5.getTableCellEditorComponent 返回的组件需要添加适当的事件处理器,该处理器在用户编辑确认时(比如 JTextField 在敲回车引发 ActionPerformed 时),应该stopCellEditing 以此来通知这次编辑过程

38、已经完成,需要更新到 JTable 中。TableCellEditor 接口暗含许多内部关系,如果不能正确建立它们之间的关系,实现往往并不能复合你的需求。JTree 的 TreeCellEditor 接口和 TableCellEditor 除了获取编辑组件的方法的参数有所不同外,其他完全相同,其工作过程也类似。除了 JTable 和 JTree 外,JComboBox 也有 in-place editor,它的 editor 接口相对简单一些:public interface ComboBoxEditor /*返回编辑的组件*/public Component getEditorCompone

39、nt();/*设置要编辑的值,如果需要终止正在编辑的其他值*/public void setItem(Object anObject);/*返回当前正在编辑的值*/public Object getItem();/*全选*/public void selectAll();/*当编辑的值得到确认时或者发生变化时将会调用注册上面的 ActionListener,改方法添加ActionListener*/public void addActionListener(ActionListener l);/*删除 ActionListener*/public void removeActionListen

40、er(ActionListener l);由于 JComboBox 只有一处可以编辑,因此的编辑过程相当简单。JComboBox 将 ComboBoxEditor 提供组件作为编辑器添加到组件树上,自己注册为该 ComboBoxEditor 的 ActionListener。当编辑组件的值发生变化,或用户确认编辑结果时,通知JComboBox。JComboBox 发出适当的事件通知 JComboBox 的外部事件侦听者。当用户从列表中选择某项进行编辑时,JComboBox 使用 ComboBoxEditor.setItem 设置编辑器的初始值。当用户请求 JComboBox 获取当前编辑值时,

41、JComboBox 调用ComboBoxEditor.getItem 获取正在编辑的值,另外 JComboBox 可以通过 ComboBoxEditor的 selectAll 来请求全选操作,这时允许如 JTextField 为编辑组件的编辑器实现全选。ComboBoxEditor 接口的方法也暗含几个关系:1.setItem、getItem、selectAll 的操作对象应该是 getEditorComponent 返回的同一组件。2.同样要实现 addActionListener 和 removeActionListener,一般要实现fireActionPerformed,要侦听编辑组件

42、的事件,使用 fireActionPerformed 通知JComboBox 做出响应。编辑器工作过程相对比 Renderer 要复杂一些,主要是因为编辑过程是和用户进行交互的过程,不像 Renderer 那样只是简单的渲染过程。这个过程是非过程性的,所以它们的接口也就复杂的多,接口方法之间也暗含这一定的关系。但要正确理解也不难,关键要清楚 JTable、JTree 和 JComboBox 编辑器工作的过程。知道这些过程并根据以及前所学的事件及事件器处理模型知识,就应该很容易理解各个接口方法的含义以及它们之间暗含的关系,也就不会在实现自己的 Editor 时一头雾水,无所适从。由于篇幅的原因,

43、今天文章就到此为止了。明天的文章将举一些具体例子加深对 in-place editor 的理解。昨天文章介绍 JTable 的 TableCellEditor 时提到,TableCellEditor 接口中的方法暗含许多关系,如过实现不能正确建立这些关系,会导致自定义的编辑器不能正常工作。记住这些关系往往使人很苦恼。有没有办法来封装这些关系,只留下简单的编程接口?办法就是写一个 TableCellEditor 的子类,所谓的框架支持(Support)类,将暗含关系进行封装,将需要自定义扩展的特征留给 Support 子类来完成。本文举一例子,实现如下图所示、类似于 IDE 界面设计工具的属性表

44、。此例将向你演示如何自定义扩展 TableCellEditor、TableCellRenderer 以及 TableModel,以便将这几天讲的知识串一下。此例中属性表区别于普通表的特征包括:1.属性值一列不同行显示不同类型的数据。2.属性值单元格采用不同的渲染组件和编辑组件。3.属性值单元格的编辑器和渲染组件是同一种组件。该例子包括如下图所示八个文件:TableCellSupport 实现了 TableCellEditor 和 TableCellRenderer 两个接口,是扩展自定义渲染器及编辑器的基类。该类实现了 TableCellEditor 和 TableCellRenderer 的

45、所有方法,封装了 TableCellEditor 所暗含的关系,并假定负责渲染的组件和负责编辑的组件为同一组件。org.dyno.test.impl 包下的类继承该 TableCellSupport 类,分别实现了CheckBox、 ComboBox、 Spinner 以及 TextField 常见类型的渲染器编辑器。要实现其他类型的自定义渲染器编辑器,可继承 TableCellSupport 进行扩展。BeanProperty 只是简单封装了某 JavaBean 属性以及渲染编辑器的对象。BeanPropertyTable 继承 JTable,以 BeanProperty 数组作为数据源。P

46、ropertyDemo 是该例子的主类,是一个 JFrame。TableCellSupport 是实现该属性表编辑器的核心类,下面是 TableCellSupport 的实现:public abstract class TableCellSupportimplements TableCellEditor, TableCellRenderer /编辑器、渲染器缺省的前后背景static Color BACKGROUND=UIManager.getColor(“TextField.background“);static Color FOREGROUND=UIManager.getColor(“Te

47、xtField.foreground“);static Color SELECTION_BACKGROUND=UIManager.getColor(“TextField.selectionBackground“);static Color SELECTION_FOREGROUND=UIManager.getColor(“TextField.selectionForeground“);/渲染器、编辑器的组件,使用同一个protected T component;/CellEditorListener 的容器,使用 WeakReference 放置内存泄漏private ArrayList lis

48、teners=new ArrayList();/构造函数public TableCellSupport(T component) ponent=component;/如果是 JComponent 类组件,为了美观把边框去掉if(component instanceof JComponent)(JComponent)component).setBorder(null);/获取并配置编辑组件public Component getTableCellEditorComponent(JTable table,Object value, boolean isSelected, int row, int

49、column) /将 value 值设置给 component,这儿调用了一个子类需要实现的方法 setValueTosetValueTo(component, value);/设置前后景、字体component.setBackground(BACKGROUND);component.setForeground(FOREGROUND);component.setFont(table.getFont();return component;/获取当前编辑器的值,以 component 中的值为准public Object getCellEditorValue() /调用了一个子类需要实现的方法 getValueFrom 从 component 获取当前正在编辑的值return getValueFrom(component);/根据事件 anEvent 判断是否可编辑,直接返回 true,如有特殊需

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报