樹狀單元的類別為javafx.scene.control.TreeCell,繼承自TreeCell的類別包括:
- 核取方塊樹狀單元:CheckBoxTreeCell.
- 選項方塊樹狀單元:ChoiceBoxTreeCell.
- 複合方塊樹狀單元:ComboBoxTreeCell.
- 文字欄位樹狀單元:TextFieldTreeCell.
private final class TreeCellCallback extends TreeCell<String> { TextField textfield; ContextMenu contextmenu = new ContextMenu(); // 建構函式 public TreeCellCallback() { MenuItem menuitem = new MenuItem("Add Tree Node"); menuitem.setGraphic(new ImageView(new Image( getClass().getResourceAsStream("images/node.gif")))); menuitem.setOnAction((ActionEvent e) -> { TreeItem treeitem = new TreeItem<>("New Tree Node...", new ImageView(imgFile)); getTreeItem().getChildren().add(treeitem); }); contextmenu.getItems().add(menuitem); } @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (empty) { setText(null); setGraphic(null); } else { setText(getItem() == null ? "" : getItem()); setGraphic(getTreeItem().getGraphic()); if (!getTreeItem().isLeaf() && getTreeItem().getParent()!= null){ setContextMenu(contextmenu); } } } } ...待完成自定類別之後,須以TreeView類別的setCellFactory()方法以下列方式設定Cell Factory的回呼函式:
treeView.setCellFactory( new Callback<TreeView<String>, TreeCell<String>>(){ @Override public TreeCell<String> call(TreeView<String> value) { return new TreeCellCallback(); } } ); ...【執行結果】
以開始編輯為例,在覆寫startEdit()方法中,當以滑鼠點選節點時,則以setGraphic()方法將節點設定為文字欄位,以此編輯節點標題。此外,並以setOnKeyReleased()方法處理在節點文字欄位釋放鍵盤按鍵時之事件,若按下Enter鍵,代表完成輸入,則以commitEdit()方法完成編輯樹狀單元;若按下ESC鍵,代表取消輸入,則以cancelEdit()方法取消編輯樹狀單元:
// 覆寫TreeCell類別的startEdit()方法 @Override public void startEdit() { super.startEdit(); if (textfield == null) { textfield = new TextField(getItem() == null ? "" : getItem()); textfield.setOnKeyReleased((KeyEvent e) -> { if (e.getCode() == KeyCode.ENTER){ // 完成編輯樹狀單元 commitEdit(textfield.getText()); } else if (e.getCode() == KeyCode.ESCAPE) { // 取消編輯樹狀單元 cancelEdit(); } }); } setText(null); // 將節點設定為文字欄位 setGraphic(textfield); textfield.selectAll(); } ...以取消編輯為例,在覆寫cancelEdit()方法中,由於取消編輯並未改變樹狀單元的內容,因此分別以setText()與setGraphic()方法設定為原標題文字與圖像,以恢復節點為原來的內容:
// 覆寫TreeCell類別的cancelEdit()方法 @Override public void cancelEdit() { super.cancelEdit(); // 設定為原標題文字 setText((String) getItem()); // 將節點設定為原圖像 setGraphic(getTreeItem().getGraphic()); } ...須注意的是,由於需要編輯節點,因此須以TreeView類別的setEditable()方法設定Tree View為可編輯狀態,並以TreeView類別的setCellFactory()方法以下列方式設定Cell Factory的回呼函式:
treeView.setEditable(true); treeView.setCellFactory( new Callback<TreeView<String>, TreeCell<String>>(){ @Override public TreeCell<String> call(TreeView<String> value) { return new TreeCellCallback(); } } ); ...【執行結果】
藉由繼承TreeCell類別之自定類別做為setCellFactory()方法的回呼函式,可使用各種物件取代原樹狀節點,以便編輯節點內容。
此方式雖然可行,但必須覆寫TreeCell類別的startEdit()、cancelEdit()、commitEdit()與updateItem()方法,因此有一定難度。 此外,JavaFX提供以下類別,可分別以核取方塊、選項方塊、複合方塊與文字欄位等取代原樹狀單元,類別彼此之間所提供的方法十分類似,使用上亦很容易:
- 核取方塊樹狀單元:CheckBoxTreeCell.
- 選項方塊樹狀單元:ChoiceBoxTreeCell.
- 複合方塊樹狀單元:ComboBoxTreeCell.
- 文字欄位樹狀單元:TextFieldTreeCell.
// 建立TreeView物件 TreeView treeView = new TreeView(); // 設定樹狀結構的根節點 treeView.setRoot(treeRoot); // 設定複選模式 treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); // 設定是否顯示根節點 treeView.setShowRoot(true); // 設定是否可以編輯 treeView.setEditable(true); // 設定Cell Factory treeView.setCellFactory(CheckBoxTreeCell.<String>forTreeView()); ...【執行結果】
ChoiceBoxTreeCell類別類似於ChoiceBox類別,以建立選項方塊樣式的樹狀節點。以下範例以TreeItem類別建立樹狀節點,並以TreeView類別的setCellFactory()方法設定Cell Factory為ChoiceBoxTreeCell,並以其forTreeView()方法設定以選項方塊取代原樹狀節點,當點選節點時,則以「下拉式選單」的方式列出選項項目,其中以ObservableList設定選項方塊的選項項目:
// 建立TreeView物件 TreeView treeView = new TreeView(); // 設定樹狀結構的根節點 treeView.setRoot(treeRoot); // 設定複選模式 treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); // 設定是否顯示根節點 treeView.setShowRoot(true); // 設定是否可以編輯 treeView.setEditable(true); // 設定選項方塊的選項項目 ObservableList<String> items = FXCollections.observableArrayList( "Profile", "Course", "Publication", "Book", "Project"); // 設定Cell Factory treeView.setCellFactory(ChoiceBoxTreeCell.forTreeView(items)); ...【執行結果】
ComboBoxTreeCell類別類似於ComboBox類別,以建立複合方塊樣式的樹狀節點。以下範例以TreeItem類別建立樹狀節點,並以TreeView類別的setCellFactory()方法設定Cell Factory為ComboBoxTreeCell,並以其forTreeView()方法設定以複合方塊取代原樹狀節點,當點選節點時,則以「下拉式選單」的方式列出選項項目,其中以ObservableList設定複合方塊的選項項目:
// 建立TreeView物件 TreeView treeView = new TreeView(); // 設定樹狀結構的根節點 treeView.setRoot(treeRoot); // 設定複選模式 treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); // 設定是否顯示根節點 treeView.setShowRoot(true); // 設定是否可以編輯 treeView.setEditable(true); // 設定複合方塊的選項項目 ObservableList<String> items = FXCollections.observableArrayList( "Profile", "Course", "Publication", "Book", "Project"); // 設定Cell Factory treeView.setCellFactory(ComboBoxTreeCell.forTreeView(items)); ...【執行結果】
TextFieldTreeCell類別類似於TextField類別,以建立文字欄位樣式的樹狀節點,當以滑鼠點選節點時,則將原節點轉換為文字欄位,以此編輯節點標題。以下範例以TreeItem類別建立樹狀節點,並以TreeView類別的setCellFactory()方法設定Cell Factory為TextFieldTreeCell,並以其forTreeView()方法設定以文字欄位取代原樹狀節點,當以滑鼠點選節點時,則將原節點轉換為文字欄位,以此編輯節點標題:
// 建立TreeView物件 TreeView treeView = new TreeView(); // 設定樹狀結構的根節點 treeView.setRoot(treeRoot); // 設定複選模式 treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); // 設定是否顯示根節點 treeView.setShowRoot(true); // 設定是否可以編輯 treeView.setEditable(true); // 設定Cell Factory treeView.setCellFactory(TextFieldTreeCell.forTreeView()); ...【執行結果】
【參考資料】
[1] Java Official Web Site:http://www.oracle.com/technetwork/java/index.html
[2] JavaFX:http://www.oracle.com/technetwork/java/javafx
[3] JavaFX 8.0 API Specification.
[4] Java Platform, Standard Edition 8 API Specification.
© Chia-Hui Huang
沒有留言:
張貼留言