使用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
這個函數判斷是否存在一個占位房屋的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、未來優化
由於時間比較緊張,這個部分還有很大的優化空間。由於樹表計算部分設置在控制器的初始化函數中,因此每次打開房屋頁面都要重新計算樹表,在房屋數量較多時,這會造成性能浪費。因此,可以在創建每個新房屋時,將該房屋加入樹表中,並將這個樹表儲存起來。每次打開頁面時便免去了複雜的計算。