一、最终效果预览
运行程序后,展示一个学生信息表格,支持增加、删除、修改操作:
表格包含「姓名」「年龄」「战斗力」「是否无敌」四列,顶部有三个操作按钮。
二、核心组件介绍
2.1 数据模型:Student 实体类
TableView 的每一行数据对应一个 Java Bean 对象,类必须是public的:
publicclassStudent{privateStringname;privateintage;privatedoublescore;privatebooleanis;publicStudent(Stringname,intage,doublescore,booleanis){this.name=name;this.age=age;this.score=score;this.is=is;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicdoublegetScore(){returnscore;}publicvoidsetScore(doublescore){this.score=score;}publicbooleanisIs(){returnis;}publicvoidsetIs(booleanis){this.is=is;}}注意:属性名和 getter/setter 方法命名要规范,后续
PropertyValueFactory会通过反射自动匹配。
2.2 数据源:ObservableList
ObservableList<Student>list=FXCollections.observableArrayList();ObservableList是可观察的列表,数据变化会自动同步到 TableView 界面。
2.3 表格组件:TableView
TableView<Student>tableView=newTableView<>(list);构造时传入数据源,TableView 会自动监听列表变化。
三、列定义与数据绑定
TableView 的核心特点是以列为单位进行配置。每列通过TableColumn定义,并通过setCellValueFactory()绑定数据。
3.1 方式一:Callback(灵活但冗长)
TableColumn<Student,String>colName=newTableColumn<>("姓名");colName.setCellValueFactory(newCallback<TableColumn.CellDataFeatures<Student,String>,ObservableValue<String>>(){@OverridepublicObservableValue<String>call(TableColumn.CellDataFeatures<Student,String>param){returnnewSimpleStringProperty(param.getValue().getName());}});tableView.getColumns().add(colName);3.2 方式二:PropertyValueFactory(简洁推荐)
TableColumn<Student,String>colName=newTableColumn<>("姓名");colName.setCellValueFactory(newPropertyValueFactory<>("name"));tableView.getColumns().add(colName);
PropertyValueFactory<>("name")会自动调用Student.getName()获取值。属性名必须与 getter 方法对应(去掉 get 前缀,首字母小写)。
四、完整代码实现
importjavafx.application.Application;importjavafx.collections.FXCollections;importjavafx.collections.ObservableList;importjavafx.geometry.Insets;importjavafx.scene.Scene;importjavafx.scene.control.Button;importjavafx.scene.control.TableColumn;importjavafx.scene.control.TableView;importjavafx.scene.control.cell.PropertyValueFactory;importjavafx.scene.layout.HBox;importjavafx.scene.layout.VBox;importjavafx.stage.Stage;publicclassTableViewDemoextendsApplication{privateTableView<Student>tableView;privateObservableList<Student>list;@Overridepublicvoidstart(StageprimaryStage){// 1. 初始化数据源list=FXCollections.observableArrayList(newStudent("燕双鹰",18,98.0,true),newStudent("李大喜",15,75.0,false),newStudent("李元芳",25,99.0,true),newStudent("刘洪",45,88.0,false),newStudent("石敢当",999,100.0,true));// 2. 创建 TableViewtableView=newTableView<>(list);tableView.setPrefHeight(400);// 3. 定义列TableColumn<Student,String>colName=newTableColumn<>("姓名");colName.setCellValueFactory(newPropertyValueFactory<>("name"));TableColumn<Student,Integer>colAge=newTableColumn<>("年龄");colAge.setCellValueFactory(newPropertyValueFactory<>("age"));TableColumn<Student,Double>colScore=newTableColumn<>("战斗力");colScore.setCellValueFactory(newPropertyValueFactory<>("score"));TableColumn<Student,Boolean>colIs=newTableColumn<>("是否无敌");colIs.setCellValueFactory(newPropertyValueFactory<>("is"));tableView.getColumns().addAll(colName,colAge,colScore,colIs);// 4. 创建操作按钮ButtonaddBtn=newButton("增加一行");ButtondelBtn=newButton("删除第一行");ButtonmodBtn=newButton("修改第一行");addBtn.setOnAction(e->addRow());delBtn.setOnAction(e->deleteRow());modBtn.setOnAction(e->modifyRow());HBoxbtnBox=newHBox(20);btnBox.setPadding(newInsets(10));btnBox.getChildren().addAll(addBtn,delBtn,modBtn);// 5. 布局VBoxroot=newVBox(10);root.setPadding(newInsets(10));root.getChildren().addAll(btnBox,tableView);Scenescene=newScene(root,500,500);primaryStage.setTitle("JavaFX TableView 演示");primaryStage.setScene(scene);primaryStage.show();}// 增加一行privatevoidaddRow(){StudentnewStudent=newStudent("新同学",20,60.0,false);// 方式1:通过 tableView.getItems()tableView.getItems().add(newStudent);// 方式2:直接操作 list(效果相同)// list.add(newStudent);}// 删除第一行privatevoiddeleteRow(){if(!tableView.getItems().isEmpty()){// 方式1:通过 tableView.getItems()tableView.getItems().remove(0);// 方式2:直接操作 list// list.remove(0);}}// 修改第一行privatevoidmodifyRow(){if(!tableView.getItems().isEmpty()){Studentfirst=tableView.getItems().get(0);// 方式1:替换整行对象tableView.getItems().set(0,newStudent("已修改",99,999.0,true));// 方式2:修改对象属性(需要属性绑定才能自动刷新)// first.setName("已修改");}}publicstaticvoidmain(String[]args){launch(args);}}五、增删改操作详解
5.1 增加数据
// 方式1:通过 TableView 的 itemstableView.getItems().add(newStudent("新同学",20,60.0,false));// 方式2:直接操作 ObservableList(效果相同)list.add(newStudent("新同学",20,60.0,false));两种方式完全等价,因为
tableView.getItems()返回的就是构造时传入的list。
5.2 删除数据
// 删除指定索引行tableView.getItems().remove(0);// 删除指定对象tableView.getItems().remove(student);// 删除选中行Studentselected=tableView.getSelectionModel().getSelectedItem();tableView.getItems().remove(selected);5.3 修改数据
// 方式1:替换整行对象tableView.getItems().set(0,newStudent("已修改",99,999.0,true));// 方式2:修改对象属性(需配合属性绑定)Studentfirst=tableView.getItems().get(0);first.setName("已修改");方式2 修改属性后界面不会自动刷新,需要使用
SimpleXxxProperty属性绑定(见下文进阶)。
六、进阶:使用属性绑定实现自动刷新
如果希望修改对象属性后界面自动更新,需要将实体类改为使用 JavaFX 属性:
importjavafx.beans.property.*;publicclassStudentProperty{privatefinalStringPropertyname=newSimpleStringProperty();privatefinalIntegerPropertyage=newSimpleIntegerProperty();privatefinalDoublePropertyscore=newSimpleDoubleProperty();privatefinalBooleanPropertyis=newSimpleBooleanProperty();publicStudentProperty(Stringname,intage,doublescore,booleanis){this.name.set(name);this.age.set(age);this.score.set(score);this.is.set(is);}// JavaFX 属性 getterpublicStringPropertynameProperty(){returnname;}publicIntegerPropertyageProperty(){returnage;}publicDoublePropertyscoreProperty(){returnscore;}publicBooleanPropertyisProperty(){returnis;}// 普通 getter/setterpublicStringgetName(){returnname.get();}publicvoidsetName(Stringname){this.name.set(name);}publicintgetAge(){returnage.get();}publicvoidsetAge(intage){this.age.set(age);}publicdoublegetScore(){returnscore.get();}publicvoidsetScore(doublescore){this.score.set(score);}publicbooleanisIs(){returnis.get();}publicvoidsetIs(booleanis){this.is.set(is);}}使用属性类后,修改属性时界面会自动刷新:
StudentPropertyfirst=tableView.getItems().get(0);first.setName("自动刷新");// 界面会立即更新!常用 API 速查表
| 操作 | API |
|---|---|
| 添加行 | tableView.getItems().add(obj)/list.add(obj) |
| 删除指定行 | tableView.getItems().remove(index) |
| 删除选中行 | tableView.getItems().remove(tableView.getSelectionModel()) |
| 替换行 | tableView.getItems().set(index, newObj) |
| 清空表格 | tableView.getItems().clear() |
| 获取选中项 | tableView.getSelectionModel().getSelectedItem() |
| 获取选中索引 | tableView.getSelectionModel().getSelectedIndex() |
| 设置选中 | tableView.getSelectionModel().select(index) |
| 设置列宽 | colName.setPrefWidth(100) |
| 禁止列拖动 | tableView.setColumnResizePolicy(TableView) |
总结
| 知识点 | 要点 |
|---|---|
| 数据模型 | 每行对应一个 Java Bean,属性需有 getter/setter |
| ObservableList | FXCollections.observableArrayList()创建可观察数据源 |
| 列定义 | PropertyValueFactory<>("属性名")自动绑定 getter |
| 增删改 | 操作tableView.getItems()或原始list均可 |
| 自动刷新 | 使用SimpleXxxProperty属性类,修改属性后界面自动更新 |