使用Javafx插件的TreeTableView控件,令一個類以樹狀表格的形式顯示。
在使用Javafx插件開發作業項目時,我需要将房屋以樹狀表格的形式顯示出來。
實作的效果:
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。
在右側視窗設定TreeTableView與每個TreeTableColumn的fx:id。
在項目中建立一個控制類(我将其命名為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()函數中,進行房屋周遊,每次循環取出一間房屋。每次循環的流程圖如下所示:
為了減少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()));
}
最後運作就可以達到樹表的效果。
4、未來優化
由于時間比較緊張,這個部分還有很大的優化空間。由于樹表計算部分設定在控制器的初始化函數中,是以每次打開房屋頁面都要重新計算樹表,在房屋數量較多時,這會造成性能浪費。是以,可以在建立每個新房屋時,将該房屋加入樹表中,并将這個樹表儲存起來。每次打開頁面時便免去了複雜的計算。