天天看點

【Javafx】以樹狀清單的形式顯示類(TreeTableView控件的使用)

【Javafx】以樹狀清單的形式顯示類(TreeTableView控件的使用)

使用Javafx插件的TreeTableView控件,令一個類以樹狀表格的形式顯示。

在使用Javafx插件開發作業項目時,我需要将房屋以樹狀表格的形式顯示出來。

實作的效果:

【Javafx】以樹狀清單的形式顯示類(TreeTableView控件的使用)

1、簡單介紹

在這裡簡單介紹一下我的程式中涉及到的類的屬性。

在我的程式中,需要顯示的類為House類。

House類的屬性如下所示。我需要将樓盤、房屋編号、購房合同編号、移交日期、所屬會員ID與備注顯示在表格中。

public class House implements Serializable
{
    String code = "";//房屋編号
    String houseName = "";//樓盤
    String houseNumber = "";//樓号
    String houseFloor = "";//樓層
    String roomNumber = "";//房間号
    String purchaseNumber = "";//購房合同編号
    String purchaseDate = "";//移交日期
    String add = "";//備注
    String houseOwnerID = "";//所屬會員ID
...下面的代碼略
           

使用HouseList作為House的集合類。

public class HouseList implements Iterable<House>, Serializable
{
    public ArrayList<House> houselist = new ArrayList<>();

    /**
     * 添加一個房屋到清單
     * @param house 添加的房屋
     */
    public void add(House house)
    {
        this.houselist.add(house);
    }

    @Override
    public Iterator iterator()
    {
        return this.houselist.iterator();
    }
}
           

在Structure類中執行個體化一個HouseList對象。這個HouseList對象存儲有要顯示的房屋。

2、整體思路

我的整體的思路是:

在建立頁面時,Javafx會調用頁面的控制器(Controller)中的initialize()函數進行頁面的初始化。

是以,我在該函數中周遊房屋列并完成樹表的建立。

3、具體實作

首先使用Scene Builder建立一個頁面,添加TreeTableView元件,并添加多個TreeTableColumn。

【Javafx】以樹狀清單的形式顯示類(TreeTableView控件的使用)

在右側視窗設定TreeTableView與每個TreeTableColumn的fx:id。

【Javafx】以樹狀清單的形式顯示類(TreeTableView控件的使用)

在項目中建立一個控制類(我将其命名為AdminInterface_House_Controller),并将剛才建立的頁面的fxml檔案中的Controller設定為這個類。

在建立的控制類中添加屬性。

注意:屬性的命名與剛才設定的fx:id一緻。
public class AdminInterface_House_Controller {
    @FXML
    private TreeTableView<House> table;
    @FXML
    private TreeTableColumn<House, String> houseTree_List;
    @FXML
    private TreeTableColumn<House, String> purchaseNumber_List;
    @FXML
    private TreeTableColumn<House, String> purchaseDate_List;
    @FXML
    private TreeTableColumn<House, String> add_List;
    @FXML
    private TreeTableColumn<House, String> houseOwnerID_List;
    @FXML
    private TreeTableColumn<House, String> code_List;
...下面的代碼省略
           

在這個類中建立初始化方法。我們将在這個函數中完成完成樹表的建立。

@FXML
private void initialize() {
    
}
           

initialize()函數中,進行房屋周遊,每次循環取出一間房屋。每次循環的流程圖如下所示:

【Javafx】以樹狀清單的形式顯示類(TreeTableView控件的使用)

為了減少initialize()中的代碼,我先定義了一個repeatText()方法。這個方法輸入一個ObservableList<TreeItem>與String,前者是一個占位房屋清單,後者是一個字元串。

這個函數判斷是否存在一個占位房屋的roomNumber變量與輸入的字元串相同。

如果存在,則說明輸入的字元串重複,該函數輸出重複位置。如果不存在,函數輸出-1。

private int repeatText(ObservableList<TreeItem<House>> list, String text){  
    //輸出-1代表不重複,輸出其他自然數代表重複位置,如0代表與第一個節點重複  
    int i = -1;  
    House temp;  
    for (TreeItem<House> treeItem : list){  
        i++;  
        temp = treeItem.getValue();  
        if (text.equals(temp.getRoomNumber())){  
            //由于輸入的是占位房屋清單,隻有roomNumber變量有值。是以隻需要判斷text是否與roomNumber相同即可。
            //重複  
            return i;  
        }  
    }  
    //不重複  
    return -1;  
}  
           

為了便于建立占位房屋,我還在House類中重載了構造函數。

public House(String roomNumber){
    this.roomNumber = roomNumber;
}
           

initialize()函數的具體代碼較為複雜,具體如下所示。

@FXML  
private void initialize() {  
    //根節點root  
    TreeItem<House> root = new TreeItem<>( new House("房屋清單"));  
    //綁定root  
    table.setRoot(root);  
    root.setExpanded(true);  
    //周遊房屋清單  
    for (House house : Structure.getStructure().houseList){  
        //對于取出的house  
        //取樓盤  
        //檢查重複性  
        if (repeatText(root.getChildren(), house.getHouseName()) == -1){  
            //樓盤不重複  
            //樓盤  
            //建立占位房屋,作為根節點的子節點  
            root.getChildren().add(new TreeItem<House>(new House(house.getHouseName())));  
            //樓号  
            int pos = root.getChildren().size()-1;  
            //建立占位房屋,作為子節點  
            root.getChildren().get(pos).setExpanded(true);  
            root.getChildren().get(pos).getChildren().add(  
                    new TreeItem<House>(new House(house.getHouseNumber()))  
            );  
            //樓層  
            //建立占位房屋,作為子節點  
            root.getChildren().get(pos).getChildren().get(0).setExpanded(true);  
            root.getChildren().get(pos).getChildren().get(0).getChildren().add(  
                    new TreeItem<House>(new House(house.getHouseFloor()))  
            );  
            //房屋存入  
            root.getChildren().get(pos).getChildren().get(0).getChildren()  
                    .get(0).setExpanded(true);  
            root.getChildren().get(pos).getChildren().get(0).getChildren()  
                    .get(0).getChildren().add(new TreeItem<House>(house));  
        }else {  
            //樓盤重複  
            //樓盤在root中的位置nameRepeatPos  
            int nameRepeatPos = repeatText(root.getChildren(), house.getHouseName());  
            //檢查樓号重複性  
            if (repeatText(root.getChildren().get(nameRepeatPos).getChildren(), house.getHouseNumber()) == -1){  
                //樓盤重複,但樓号不重複  
                //樓号  
                root.getChildren().get(nameRepeatPos).setExpanded(true);  
                root.getChildren().get(nameRepeatPos).getChildren().add(  
                        new TreeItem<House>(new House(house.getHouseNumber()))  
                );  
                //樓層  
                int pos = root.getChildren().get(nameRepeatPos).getChildren().size()-1;  
                root.getChildren().get(nameRepeatPos).getChildren().get(pos).setExpanded(true);  
                root.getChildren().get(nameRepeatPos).getChildren().get(pos).getChildren().add(  
                        new TreeItem<House>(new House(house.getHouseFloor()))  
                );  
                //房屋存入  
                root.getChildren().get(nameRepeatPos).getChildren().get(pos).getChildren()  
                        .get(0).setExpanded(true);  
                root.getChildren().get(nameRepeatPos).getChildren().get(pos).getChildren()  
                        .get(0).getChildren().add(new TreeItem<House>(house));  
            }else {  
                //樓盤重複,樓号重複  
                //樓号在root中的位置numRepeatPos  
                int numRepeatPos = repeatText(root.getChildren().get(nameRepeatPos).getChildren(), house.getHouseNumber());  
                //檢查樓層重複性  
                if (repeatText(  
                        root.getChildren().get(nameRepeatPos).getChildren().get(numRepeatPos).getChildren()  
                        , house.getHouseFloor()) == -1){  
                    //樓盤重複,樓号重複,樓層不重複  
                    root.getChildren().get(nameRepeatPos).getChildren().get(numRepeatPos).setExpanded(true);  
                    root.getChildren().get(nameRepeatPos).getChildren().get(numRepeatPos).getChildren().add(  
                            new TreeItem<House>(new House(house.getHouseFloor()))  
                    );  
                    //房屋存入  
                    int pos = root.getChildren().get(nameRepeatPos).getChildren().get(numRepeatPos).getChildren().size()-1;  
                    root.getChildren().get(nameRepeatPos).getChildren().get(numRepeatPos).getChildren()  
                            .get(pos).setExpanded(true);  
                    root.getChildren().get(nameRepeatPos).getChildren().get(numRepeatPos).getChildren()  
                            .get(pos).getChildren().add(new TreeItem<House>(house));  
                }else {  
                    //樓盤重複,樓号重複,樓層重複  
                    //樓層root中的位置floorRepeatPos  
                    int floorRepeatPos = repeatText(  
                            root.getChildren().get(nameRepeatPos).getChildren().get(numRepeatPos).getChildren()  
                            , house.getHouseFloor());  
                    //房屋存入  
                    root.getChildren().get(nameRepeatPos).getChildren().get(numRepeatPos).getChildren()  
                            .get(floorRepeatPos).setExpanded(true);  
                    root.getChildren().get(nameRepeatPos).getChildren().get(numRepeatPos).getChildren()  
                            .get(floorRepeatPos).getChildren().add(new TreeItem<House>(house));  
                }  
            }  
        }  
    }  
    //向清單中添加條目  
    houseTree_List.setCellValueFactory((TreeTableColumn.CellDataFeatures<House, String> houseTemp) ->  
            new eadOnlyStringWrapper(houseTemp.getValue().getValue().getRoomNumber()));  
    purchaseNumber_List.setCellValueFactory((TreeTableColumn.CellDataFeatures<House, String> houseTemp) ->  
            new ReadOnlyStringWrapper(houseTemp.getValue().getValue().getPurchaseNumber()));  
    code_List.setCellValueFactory((TreeTableColumn.CellDataFeatures<House, String> houseTemp) ->  
            new ReadOnlyStringWrapper(houseTemp.getValue().getValue().getCode()));  
    houseOwnerID_List.setCellValueFactory((TreeTableColumn.CellDataFeatures<House, String> houseTemp) ->  
            new ReadOnlyStringWrapper(houseTemp.getValue().getValue().getHouseOwnerID()));  
    add_List.setCellValueFactory((TreeTableColumn.CellDataFeatures<House, String> houseTemp) ->  
            new ReadOnlyStringWrapper(houseTemp.getValue().getValue().getAdd()));  
    purchaseDate_List.setCellValueFactory((TreeTableColumn.CellDataFeatures<House, String> houseTemp) ->  
            new ReadOnlyStringWrapper(houseTemp.getValue().getValue().getPurchaseDate()));  
  
}  
           

最後運作就可以達到樹表的效果。

【Javafx】以樹狀清單的形式顯示類(TreeTableView控件的使用)

4、未來優化

由于時間比較緊張,這個部分還有很大的優化空間。由于樹表計算部分設定在控制器的初始化函數中,是以每次打開房屋頁面都要重新計算樹表,在房屋數量較多時,這會造成性能浪費。是以,可以在建立每個新房屋時,将該房屋加入樹表中,并将這個樹表儲存起來。每次打開頁面時便免去了複雜的計算。