JavaFX Cell Factory(4)樹狀表格 by 黃嘉輝 | CodeData
top

JavaFX Cell Factory(4)樹狀表格

分享:

JavaFX Cell Factory(3)表格物件 << 前情

JavaFX 8新增樹狀表格 (Tree Table),樹狀表格結合樹與表格物件,因此樹狀表格與後兩者十分類似,特色是將樹狀物件置於表格單元之中,讓表格單元中的資料以階層的方式呈現,下圖為樹狀表格的樣式:

Tree Table

其中:

  • Tree Table View:樹狀表格。
  • Tree Table Header:樹狀表格標題。
  • Tree Table Column:樹狀表格直行。
  • Tree Table Row:樹狀表格橫列。
  • Tree Table Cell:樹狀表格單元。
  • Tree Item:樹狀節點。
  • Table Menu Button:表格選單按鈕。
  • Column Sorter:表格直行排序器,可針對直行排序。
  • Editable Cell:可編輯的樹狀表格單元。
  • Vertical Line:垂直格線。
  • Scrollbar:捲軸,分為水平與垂直捲軸。

樹狀表格由Tree Table View、Tree Table Column、Tree Table Row與Tree Table Cell所組成,TreeTableView類別用以置放直行、橫列與樹狀表格單元,並顯示樹狀表格,為樹狀表格的最上層,如同TableViewTreeViewComboBoxListView類別一般,可修改各樹狀表格單元的形式,並分別依據直行或橫列設定其Cell Factory。

樹狀表格單元的類別為javafx.scene.control.TreeTableCell,繼承自TreeTableCell的類別包括:

  • 核取方塊樹狀表格單元:CheckBoxTreeTableCell.
  • 選項方塊樹狀表格單元:ChoiceBoxTreeTableCell.
  • 複合方塊樹狀表格單元:ComboBoxTreeTableCell.
  • 進度列樹狀表格單元:ProgressBarTreeTableCell.
  • 文字欄位樹狀表格單元:TextFieldTreeTableCell.

因此可使用核取方塊、選項方塊、複合方塊、進度列與文字欄位等取代原樹狀表格單元,較樹狀單元多了進度列物件。

以下範例以繼承TreeTableCell類別之自定TextFieldCellCallback類別做為setCellFactory()方法的回呼函式。在TextFieldCellCallback類別的建構函式中,以setAlignment()方法設定欄位內容為置中對齊:

private final class TextFieldCellCallback 
  extends TreeTableCell<Department, String> {

  TextField textfield;

  // 建構函式
  public TextFieldCellCallback() {
    // 設定欄位內容為置中對齊
    setAlignment(Pos.CENTER);
  }
  ...
}
...

TextFieldCellCallback類別中,分別覆寫TreeTableCell類別的startEdit()cancelEdit()updateItem()方法以處理開始編輯、取消編輯與更新樹狀表格單元等。

以開始編輯為例,在覆寫startEdit()方法中,當以滑鼠點選樹狀表格單元時,則以setGraphic()方法將樹狀表格單元設定為文字欄位,以此編輯樹狀表格單元的內容。此外,並以setOnKeyReleased()方法處理當在樹狀表格單元文字欄位釋放鍵盤按鍵時之事件,若按下Enter鍵,代表完成輸入,則以commitEdit()方法完成編輯樹狀表格單元;若按下ESC鍵,代表取消輸入,則以cancelEdit()方法取消編輯樹狀表格單元:

// 覆寫TreeTableCell類別的startEdit()方法
@Override public void startEdit() {
  super.startEdit();

  if (textfield == null) {
    textfield = new TextField(getItem() == null ? "" : getItem());
    textfield.setMinWidth(this.getWidth()-this.getGraphicTextGap()*2);

    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();
}
...

須注意的是,由於需要編輯樹狀表格單元,因此須以TreeTableView類別的setEditable()方法設定Tree Table View為可編輯狀態,並以TreeTableView類別的setCellFactory()方法以下列方式設定Cell Factory的回呼函式:

TreeTableView<Department> treeTableView = null;
treeTableView = new TreeTableView<>();
// 設定Tree Table View為可編輯狀態
treeTableView.setEditable(true);

// 建立直行
TreeTableColumn<Department, String> treeTableColumn1 = 
  new TreeTableColumn<>("Faculty");

// 設定Cell Factory的回呼函式
treeTableColumn1.setCellFactory(
  (TreeTableColumn<Department, String> value) -> 
  new TextFieldCellCallback());
...

【執行結果】

Tree Table

藉由繼承TreeTableCell類別之自定類別做為setCellFactory()方法的回呼函式,可使用各種物件取代原樹狀表格單元,以便編輯樹狀表格單元內容

此方式雖然可行,但必須覆寫TreeTableCell類別的startEdit()cancelEdit()commitEdit()updateItem()方法,因此有一定難度。

此外,JavaFX提供以下類別,可分別以核取方塊、選項方塊、複合方塊、進度列與文字欄位等取代原樹狀表格單元類別彼此之間所提供的方法十分類似,使用上亦很容易:

  • 核取方塊樹狀表格單元:CheckBoxTreeTableCell.
  • 選項方塊樹狀表格單元:ChoiceBoxTreeTableCell.
  • 複合方塊樹狀表格單元:ComboBoxTreeTableCell.
  • 進度列樹狀表格單元:ProgressBarTreeTableCell.
  • 文字欄位樹狀表格單元:TextFieldTreeTableCell.

CheckBoxTreeTableCell類別類似於CheckBoxTableCell類別,以建立核取方塊樣式的樹狀表格單元,功能與核取方塊十分類似,其選取狀態分為未勾選與已勾選。以下範例以TreeTableColumn類別的setCellFactory()方法設定Cell Factory為CheckBoxTreeTableCell,並以其forTreeTableColumn()方法以核取方塊取代原樹狀表格單元:

// 建立直行
TreeTableColumn<Department, Boolean> treeTableColumn5 = 
  new TreeTableColumn<>("Check");
// 設定直行最小寬度
treeTableColumn5.setPrefWidth(60);
// 設定直行標題的圖像
treeTableColumn5.setGraphic(new ImageView(new Image(
  getClass().getResourceAsStream("images/checkbox.gif"))));
// 設定Cell Factory
treeTableColumn5.setCellFactory(
  CheckBoxTreeTableCell.forTreeTableColumn(treeTableColumn5));
treeTableColumn5.setEditable(true);
...

【執行結果】

Tree Table

ChoiceBoxTreeTableCell類別類似於ChoiceBoxTableCell類別,以建立選項方塊樣式的樹狀表格單元,功能與選項方塊十分類似,當點選樹狀表格單元時,則以「下拉式選單」的方式列出選項項目,由於包含一個以上的選項項目,因此ChoiceBoxTreeTableCell類別必須以陣列定義一組選項項目,以做為「下拉式選單」的選項內容。以下範例以TreeTableColumn類別的setCellFactory()方法設定Cell Factory為ChoiceBoxTreeTableCell,並以其forTreeTableColumn()方法以選項方塊取代原樹狀表格單元,當點選樹狀表格單元時,則以「下拉式選單」的方式列出選項項目,其中以ObservableList設定選項方塊的選項項目:

// 建立直行
TreeTableColumn<Department, String> treeTableColumn5 = 
  new TreeTableColumn<>("Phone");
// 設定直行最小寬度
treeTableColumn5.setPrefWidth(60);
// 設定直行標題的圖像
treeTableColumn5.setGraphic(new ImageView(new Image(
  getClass().getResourceAsStream("images/choicebox.gif"))));

// 設定選項方塊的選項項目
ObservableList phonelists = FXCollections.observableArrayList(
  "4059", "4330", "5390",
  "5600", "5720", "6399",
  "6400", "6401", "6506");

// 設定Cell Factory
treeTableColumn5.setCellFactory(
  ChoiceBoxTreeTableCell.forTreeTableColumn(phonelists));
treeTableColumn5.setEditable(true);
...

【執行結果】

Tree Table

ComboBoxTreeTableCell類別類似於ComboBoxTableCell類別,以建立複合方塊樣式的樹狀表格單元,功能與複合方塊十分類似。以下範例以TreeTableColumn類別的setCellFactory()方法設定Cell Factory為ComboBoxTreeTableCell,並以其forTreeTableColumn()方法以複合方塊取代原樹狀表格單元,當點選樹狀表格單元時,則以「下拉式選單」的方式列出選項項目,其中以ObservableList設定複合方塊的選項項目:

// 建立直行
TreeTableColumn<Department, String> treeTableColumn5 = 
  new TreeTableColumn<>("Phone");
// 設定直行最小寬度
treeTableColumn5.setPrefWidth(60);
// 設定直行標題的圖像
treeTableColumn5.setGraphic(new ImageView(new Image(
  getClass().getResourceAsStream("images/combobox.gif"))));

// 設定選項方塊的選項項目
ObservableList phonelists = FXCollections.observableArrayList(
  "4059", "4330", "5390",
  "5600", "5720", "6399",
  "6400", "6401", "6506");

// 設定Cell Factory
treeTableColumn5.setCellFactory(
  ComboBoxTreeTableCell.forTreeTableColumn(phonelists));
treeTableColumn5.setEditable(true);
...

【執行結果】

Tree Table

TextFieldTreeTableCell類別類似於TextFieldTableCell類別,以建立文字欄位樣式的樹狀表格單元,當以滑鼠點選樹狀表格單元時,則將原樹狀表格單元轉換為文字欄位,以此編輯樹狀表格單元內容。以下範例以TreeTableColumn類別的setCellFactory()方法設定Cell Factory為TextFieldTreeTableCell,並以其forTreeTableColumn()方法以文字欄位取代原樹狀表格單元,當以滑鼠點選樹狀表格單元時,則將原樹狀表格單元轉換為文字欄位,以此編輯樹狀表格單元內容:

// 建立直行
TreeTableColumn<Department, String> treeTableColumn1 = 
  new TreeTableColumn<>("Faculty");
// 設定直行最小寬度
treeTableColumn1.setPrefWidth(80);
// 設定直行標題的圖像
treeTableColumn1.setGraphic(new ImageView(new Image(
  getClass().getResourceAsStream("images/faculty.gif"))));

// 設定直行對應於資料陣列的順序
treeTableColumn1.setCellValueFactory(
  (TreeTableColumn.CellDataFeatures<Department, String> param) ->
  new ReadOnlyStringWrapper(param.getValue().getValue().getFaculty())
);

// 設定Cell Factory
treeTableColumn1.setCellFactory(
  TextFieldTreeTableCell.forTreeTableColumn());
treeTableColumn1.setEditable(true);
...

【執行結果】

Tree Table

【參考資料】

[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.

後續 >> JavaFX Cell Factory(5)日期選擇器

分享:
按讚!加入 CodeData Facebook 粉絲群

相關文章

留言

留言請先。還沒帳號註冊也可以使用FacebookGoogle+登錄留言

關於作者

黃嘉輝副教授,目前任職於國立臺北商業大學企業管理學系,喜歡寫程式,特別愛Java,範例可參考教學網站

熱門論壇文章

熱門技術文章