1. 實現以“+”、“-”表示節點圖標
JavaFX中TreeView的默認節點圖標如下圖所示:
其中箭頭向下表示展開,向右則表示合攏。
設置css就可以改變TreeView的樣式。比如使用下面幾行的css定義,就可以實現“+”表示合攏,“-”表示展開。
.tree-cell .tree-disclosure-node .arrow { -fx-shape: "M 0 -1 L 3 -1 L 3 -4 L 5 -4 L 5 -1 L 8 -1 L 8 1 L 5 1 L 5 4 L 3 4 L 3 1 L 0 1 z"; } .tree-cell:expanded .tree-disclosure-node .arrow { -fx-rotate: 0; -fx-scale-shape: false; -fx-shape: "M 0 -1 L 7 -1 L 7 1 L 0 1 z"; }
這是改變後的效果:
2. JavaFX中默認TreeView樣式定義
在JavaFX的com.sun.javafx.scene.control.skin.caspian的包中,有一個caspian.css文件,裏面定義了JavaFX的默認樣式。
打開文件,搜索“Treeview”,可以找到如下內容:
/************************************************************************ * * * TreeView and TreeCell * * * ************************************************************************/ .tree-view { -fx-skin: "com.sun.javafx.scene.control.skin.TreeViewSkin"; -fx-background-color: -fx-box-border, -fx-control-inner-background; -fx-background-insets: 0, 1; /* There is some oddness if padding is in em values rather than pixels, in particular, the left border of the control doesn't show. */ -fx-padding: 1; /* 0.083333em; */ } …
其中跟節點圖標有關的定義有:
.tree-cell.tree-disclosure-node.arrow { -fx-background-color: -fx-mark-color; -fx-padding: 0.333333em; /* 4 */ -fx-shape: "M 0 -4 L 8 0 L 0 4 z"; }
.tree-cell:expanded.tree-disclosure-node.arrow { -fx-rotate: 90; } .tree-cell:filled:hover .tree-disclosure-node .arrow { -fx-background-color: -fx-mark-color; } .tree-cell:filled:selected .tree-disclosure-node .arrow { -fx-background-color: -fx-selection-bar-text; } .tree-cell:filled:selected:hover .tree-disclosure-node .arrow { -fx-background-color: -fx-selection-bar-text; }
3. 簡單介紹SVG路徑字符串
先注意其中前兩個高亮顯示的定義。“-fx-shape”是一個SVG的路徑字符串,用來畫圖形。M代表moveTo,L代表lineTo,最後的z表示連接當前點到初始點,使形狀閉合。如圖:
由此可知,在這裏使用“-fx-shape”繪製了一個向右的箭頭,是TreeItem的關閉狀態。後面的“.tree-cell:expanded .tree-disclosure-node .arrow”理所當然就是展開狀態,這倒是很簡單,“-fx-rotate: 90;”表示順時針旋轉90度,即箭頭衝下。
默認樣式就是這個原理。把前面寫的兩個選擇器放在項目的css文件中,就可以覆蓋默認樣式。其中的:
-fx-shape: "M 0 -1 L 3 -1 L 3 -4 L 5 -4 L 5 -1 L 8 -1 L 8 1 L 5 1 L 5 4 L 3 4 L 3 1 L 0 1 z";
就是手工畫了一個“+”號,如圖:
在SVG路徑字符串中,還可以用“H x”或者“V y”代替“L x y”。“H x”表示從當前位置畫水平直線到位置“x”,“V y”則表示從當前位置畫垂直線到位置“y”。
這樣之前的兩個選擇器可以寫成下面的樣子,看上去精簡了很多:
.tree-cell .tree-disclosure-node .arrow { -fx-shape: "M 0 -1 H 3 V -4 H 5 V -1 H 8 V 1 H 5 V 4 H 3 V 1 H 0 z" } .tree-cell:expanded .tree-disclosure-node .arrow { -fx-rotate: 0; -fx-scale-shape: false; -fx-shape: "M 0 -1 H 7 V 1 H 0 z"; }
4. CSS屬性覆蓋
注意,新的選擇器僅僅覆蓋了“-fx-shape”屬性,其他兩個屬性,-fx-background-color和-fx-padding仍然原樣保留。也是因此,在“.tree-cell:expanded”中一定要有 “-fx-rotate: 0;”,否則仍然會執行旋轉90度,把畫的“-”變成“|”。
還有,在“.tree-cell:expanded”中還多了屬性“-fx-scale-shape: false”。該屬性默認爲“true”,會把畫出的“-”號放大成一個矩形。
5. Win7 Style
上面提到5個關於節點圖標的選擇器中,其他3個描述的是鼠標經過,以及節點被選擇時的樣式。比如下面的定義實現了Win7效果的TreeView樣式:
.tree-cell .tree-disclosure-node .arrow { -fx-scale-shape: false; -fx-background-color: transparent; -fx-shape: "M 0 4 L 0 -4 L 5 0 z"; -fx-border-color: grey; -fx-border-width: 0.083333em; } .tree-cell:expanded .tree-disclosure-node .arrow { -fx-scale-shape: false; -fx-background-color: -fx-mark-color; -fx-rotate: 0; -fx-shape: "M 0 3 L 6 -3 L 6 3 z"; -fx-border-width: 0.083333em; } .tree-cell:filled:hover .tree-disclosure-node .arrow { -fx-background-color: transparent; -fx-border-color: cyan; } .tree-cell:filled:selected .tree-disclosure-node .arrow { -fx-border-color: cyan; } .tree-cell:filled:selected:hover .tree-disclosure-node .arrow { -fx-border-color: cyan; }
效果如圖:
不是太象,應該是有幾個JavaFX-CSS還沒掌握。
參考資料:
1. JavaFX CSS Reference Guide (http://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html)
2. SVG 1.1 (Second Edition) – 16 August 2011 (http://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand)