ASwing 中 JTree 實現 folder 自定義圖示

poplarbbs發表於2009-12-17

最近在用 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 掉。

 

我知道說起來好像很理所當然,不過在沒看程式碼的前提下還是很容易錯的。所以在此記錄一下。

相關文章