TreeTable是Tree和Table的一個結合-
就是一個即能夠展開和收起行,同時也能夠顯示多個列的組件。在Swing的標準包里沒有一個叫做JtreeTable的組件,但是我們很容易通過把Jtree做成Jtable的渲染器來創建一個這樣的組件。
這篇文章就是關于如何使用該技術來創建一個TreeTable。最后實現一個名為TreeTableExample0的例子程序,該例子實現了一個TreeTable的瀏覽器,可以用來瀏覽本機的文件系統(如下圖所示)
在Swing中,Jtree,Jtable,Jlist和JcomboBox組件都是使用一個叫做單元格渲染器(Cell Render)的指定對象來畫內容。單元格渲染器的paint()方法來畫list中的每一項,tree中的每個節點,table中的每個單元格。單元格渲染器就象一個“印章(rubber
stamp)”,它會移動到setBounds()方法指定的位置,然后用paint()方法來畫。
通過使用組件來渲染單元格,你可以僅創建一個組件來高效地顯示大量的相同組件。缺省的,Swing組件使用支持簡單的文本和圖標組合(Text和Icon)的Jlabel來做單元格的渲染器。要使用任何的Swing組件做單元格渲染器,只需創建一個實現了相應的單元格渲染器接口的子類。如:Jtable的TableCellRenderer接口,Jlist的ListCellRenderer接口,等等。
Swing中的渲染
下面是一個如何在JTable中使用JcheckBox作為渲染器的例子
public class CheckBoxRenderer extends JCheckBox
implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
setSelected(((Boolean)value).booleanValue()));
return this;
}
}
來看看下面例子是如何工作的
下面的代碼段是本文后面介紹的例子中的一個片斷 ,演示了如何用JTree來渲染JTable的內部。這個例子稍微有點兒不尋常,是因為它把JTree的每單個節點畫到JTable的每單個單元格,而不是把整個樹畫到每個JTable的單元格
我們使用通常的方法開始:通過擴展Jtree類和實現TableCellRenderer接口把Jtree展開到單元格渲染器。為了實現一個單元格渲染器所需的行為,我們必須讓我們的渲染器僅把樹的節點畫在一個特定的表單元格中。 實現這些的一個簡單方法就是重寫setBounds()方法和paint()方法,如下:
public class TreeTableCellRenderer extends JTree
implements TableCellRenderer {
protected int visibleRow;
public void setBounds(int x, int y, int w, int h) {
super.setBounds(x, 0, w, table.getHeight());
}
public void paint(Graphics g) {
g.translate(0, -visibleRow * getRowHeight());
super.paint(g);
}
public Component getTableCellRendererComponent(JTable table,
object value,
boolean isSelected,
boolean hasFocus,
int row, int column) {
visibleRow = row;
return this;
}
}
當每個單元格繪制好以后,JTable進行正常的渲染過程,設置其邊界,請求繪制。然而在本例中,我們使用一個實例變量visibleRow來記錄當前繪制的單元格的行號。同時我們重寫了setBounds(),因此即使當JTable根據當前繪制的單元格的尺寸來設定自己的邊界的時候,Jtree也能和JTable保持同意的高度。
為了完成該功能,我們還要重寫paint(), 使用已經存儲的變量visibleRow,把剪輯矩形區域移動到tree的相應部分的上方。結果是當table要求繪制的時候,Jtree 僅繪制它的其中一個節點。
除了把Jtree做成單元格第一列的渲染器,我們還把Jtree作為這些單元個的編輯器。這種作法的效果是JTable傳遞所有的鼠標和鍵盤事件給這個“編輯器” - 也就允許tree接受用戶輸入來展開和收縮它的節點。
例子:一個文件系統瀏覽器
文中的例子創建了一個文件系統瀏覽器,每個目錄可以展開和收起,表中的其它列顯示文件和目錄的重要屬性,如文件大小和日期等
下面是例子中的類文件列表,及其用途描述:
TreeTableModel.java: 新接口,擴展了TreeModel接口,描述TreeTable中要顯示那些數據
AbstractTreeTableModel.java: TreeTableModel的基類,該類處理一些監聽器。
TreeTableModelAdapter.java:? 實現了TreeModel接口的包裝類,輸入參數為TreeTableModel和Jtree
AbstractCellEditor.java:? CellEditors的基類,該類處理一些監聽器。
JTreeTable.java: JTable的子類,該類可以從TreeTableModel中渲染數據
MergeSort.java:? 一個合并排序的實現
FileSystemModel.java: 本機文件系統的模型,AbstractTreeTableModel的實子類,實現了TreeTableModel接口
TreeTableExample0.java:
顯示TreeTable的示例程序。
sources.zip:
包含上述文件的壓縮文件,當你運行程序TreeTableExample0, 顯示一個本地文件系統中文件和目錄的TreeTable。就像文章開始部分顯示的圖片。 點擊表的第一列中的支元素,項目就會象其它樹一樣的展開和收縮。