news 2026/6/15 9:56:51

JavaFX TableView 使用详解:从数据绑定到增删改

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaFX TableView 使用详解:从数据绑定到增删改

一、最终效果预览

运行程序后,展示一个学生信息表格,支持增加、删除、修改操作:

表格包含「姓名」「年龄」「战斗力」「是否无敌」四列,顶部有三个操作按钮。


二、核心组件介绍

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
ObservableListFXCollections.observableArrayList()创建可观察数据源
列定义PropertyValueFactory<>("属性名")自动绑定 getter
增删改操作tableView.getItems()或原始list均可
自动刷新使用SimpleXxxProperty属性类,修改属性后界面自动更新
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 9:55:50

如何在Google Ads投放广告|点一次要30块?这3招帮你把点击费砍一半

数据全裸露&#xff1a;新账户的前三天后台报表录入了72小时的跑单记录。账单数字停在5400元。鼠标移到点击量那一栏&#xff0c;显示只有180次。系统算出的单次点击单价稳稳停在30.1元。搜词报表里躺着85个搜索词“机械图纸免费PDF下载”。2550元预算瞬间烧光。大盘总点击率卡…

作者头像 李华
网站建设 2026/6/15 9:52:56

MVP 到底是什么

很多人第一次听到 MVP&#xff0c;会把它理解成“功能很少的产品”或者“先做一个简陋版本”。于是他把完整产品砍掉一半功能&#xff0c;页面做得粗一点&#xff0c;流程做得短一点&#xff0c;就觉得自己做了 MVP。结果上线以后&#xff0c;用户仍然不用&#xff0c;也不知道…

作者头像 李华
网站建设 2026/6/15 9:46:14

MPC8379E eLBC控制器GPCM与FCM模式配置实战指南

1. 项目概述与核心价值在嵌入式系统开发&#xff0c;尤其是基于PowerPC架构的工控、网络设备领域&#xff0c;内存控制器&#xff08;Memory Controller&#xff09;的配置往往是决定系统稳定性和性能上限的关键一环。它不像写个驱动或者调个中断那么简单&#xff0c;而是直接与…

作者头像 李华
网站建设 2026/6/15 9:46:13

MPC8379E I2C与DUART驱动开发:从寄存器配置到Boot Sequencer实战

1. 项目概述 在嵌入式系统开发中&#xff0c;通信接口是连接处理器与外部世界的桥梁&#xff0c;其稳定性和效率直接决定了整个系统的性能与可靠性。今天&#xff0c;我想结合自己多年在PowerPC架构平台上的开发经验&#xff0c;深入聊聊MPC8379E这款经典处理器中的两个核心通信…

作者头像 李华
网站建设 2026/6/15 9:45:56

别再死记硬背了!用RTA-OS配置任务优先级,这3个实战坑你踩过吗?

RTA-OS任务优先级配置实战&#xff1a;避开这3个致命陷阱在嵌入式系统开发中&#xff0c;任务调度是确保系统实时性和可靠性的核心机制。AUTOSAR RTA-OS作为汽车电子领域广泛采用的实时操作系统&#xff0c;其任务优先级配置直接影响着系统的响应速度和稳定性。本文将深入探讨三…

作者头像 李华
网站建设 2026/6/15 9:40:49

告别手动配置!PyCharm 2023.3 一键连接 GitLab 仓库的保姆级教程

PyCharm 2023.3 智能连接 GitLab 全流程解析&#xff1a;让版本控制更优雅在软件开发的世界里&#xff0c;效率就是生命线。每次IDE的版本更新&#xff0c;都意味着我们可以用更少的点击完成更多的工作。PyCharm 2023.3版本对GitLab集成的优化&#xff0c;正是这样一个能显著提…

作者头像 李华