最近在用 ASwing 做项目,需要根据节点内容自定义 folder 的图标。网上找到一些例子但总有各种各样的问题,于是通过查看 ASwing 的代码,实现了这个简单的功能。在这里跟大家分享,也记录一下比较容易错的几个点。
首先说一下ASwing渲染的结构。
大概的结构就是这样,最后每个节点的渲染是在 TreeCell 中提供图标的。所以实现功能只需要自定义一个自己的 TreeCell 子类。下面是代码:
package { import org.aswing.Icon; import org.aswing.tree.DefaultTreeCell; import org.aswing.tree.MutableTreeNode; /** * @author dengyang */ public class MyTreeCell extends DefaultTreeCell{ private var squareIcon:Icon; private var dotIcon:Icon; public function MyTreeCell(){ super(); if(squareIcon == null) { squareIcon = new SquareIcon(); } if(dotIcon == null) { dotIcon = new DotIcon(); } } override public function setCellValue(value:*) : void { super.setCellValue(value); //根据此Cell的值,如果最后一个字符数字是偶数,则使用方形图标 //否则使用圆形图标 var node:MutableTreeNode = MutableTreeNode(value); var str:String = node.getUserObject(); if(str == '德州扑克'){ expanded_folder_icon = dotIcon; collapsed_folder_icon = dotIcon; }else{ expanded_folder_icon = squareIcon; collapsed_folder_icon = squareIcon; } } } } import org.aswing.ASColor; import org.aswing.Component; import org.aswing.Icon; import org.aswing.graphics.Graphics2D; import org.aswing.graphics.SolidBrush; import flash.display.DisplayObject; import flash.display.Sprite; class SquareIcon implements Icon{ [Embed(source="dz.png")] private var dzpng : Class; private var dzIcon : DisplayObject; public function SquareIcon(){ if(dzIcon == null) { dzIcon = new dzpng(); } } public function getIconWidth(c:Component):int{ return 16; } public function getIconHeight(c:Component):int{ return 16; } public function updateIcon(c:Component, g:Graphics2D, x:int, y:int):void{ g.fillRectangle(new SolidBrush(ASColor.GREEN), x, y, 12, 12); } public function getDisplay(c:Component):DisplayObject{ return dzIcon; } } class DotIcon implements Icon{ [Embed(source="dz.png")] private var dzpng : Class; [Embed(source="lock.png")] private var lockPng : Class; private var dzIcon : Sprite; public function DotIcon(){ if(dzIcon == null) { dzIcon = new Sprite(); dzIcon.addChild(new dzpng()); dzIcon.addChild(new lockPng()); } } public function getIconWidth(c:Component):int{ return 16; } public function getIconHeight(c:Component):int{ return 16; } public function updateIcon(c:Component, g:Graphics2D, x:int, y:int):void{ g.fillCircle(new SolidBrush(ASColor.RED), x+6, y+6, 6); } public function getDisplay(c:Component):DisplayObject{ return dzIcon; } }
代码很简单,但却很容易错。我就错了两次。
起初我在每一个 getDisplay() 中都 new Icon(),造成树上的图标会有残影;后来我在 getDisplay() 中返回 static 的 Icon,同类图表中只有最后一个显示。
后来看了一下 DefaultTreeCell 父类 JLabel 中的 setIcon() ,其中有两个操作,一个是 uninstallIcon ,一个是 installIcon。如果每次都 new 新的对象会造成 uninstallIcon 中无法 remove 上次加载的 icon。而如果是静态变量的话,又会造成每次加入新的 Cell 时会把原有 icon remove 掉。
我知道说起来好像很理所当然,不过在没看代码的前提下还是很容易错的。所以在此记录一下。