在使用Javafx插件开发作业项目时,我需要将房屋以树状表格的形式显示出来。
实现的效果:
在这里简单介绍一下我的程序中涉及到的类的属性。
在我的程序中,需要显示的类为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()));
}
最后运行就可以达到树表的效果。
由于时间比较紧张,这个部分还有很大的优化空间。由于树表计算部分设置在控制器的初始化函数中,因此每次打开房屋页面都要重新计算树表,在房屋数量较多时,这会造成性能浪费。因此,可以在创建每个新房屋时,将该房屋加入树表中,并将这个树表储存起来。每次打开页面时便免去了复杂的计算。