JavaFX中TableView的使用

article/2025/8/26 14:43:07

稍微说说JavaFX里面TableView怎么用,(其实在JavaFX的源码中都有示例。。。)

首先要了解TableView是用来做什么的,TableView是JavaFX的一个表视图,用来显示表格的,在TableView的类注释中写了

/*** @see TableColumn* @see TablePosition* @param <S> The type of the objects contains within the TableView items list* @since JavaFX 2.0*/

然后看一下官方给出的示例是啥样的

Creating a TableView
Creating a TableView is a multi-step process, and also depends on the underlying data model needing to be represented. For this example we'll use an ObservableList<Person>, as it is the simplest way of showing data in a TableView. The Person class will consist of a first name and last name properties. That is:public class Person {private StringProperty firstName;public void setFirstName(String value) { firstNameProperty().set(value); }public String getFirstName() { return firstNameProperty().get(); }public StringProperty firstNameProperty() {if (firstName == null) firstName = new SimpleStringProperty(this, "firstName");return firstName;}private StringProperty lastName;public void setLastName(String value) { lastNameProperty().set(value); }public String getLastName() { return lastNameProperty().get(); }public StringProperty lastNameProperty() {if (lastName == null) lastName = new SimpleStringProperty(this, "lastName");return lastName;}public Person(String firstName, String lastName) {setFirstName(firstName);setLastName(lastName);}}The data we will use for this example is:List<Person> members = List.of(new Person("William", "Reed"),new Person("James", "Michaelson"),new Person("Julius", "Dean"));Firstly, we need to create a data model. As mentioned, for this example, we'll be using an ObservableList<Person>:ObservableList<Person> teamMembers = FXCollections.observableArrayList(members);Then we create a TableView instance:TableView<Person> table = new TableView<>();table.setItems(teamMembers);With the items set as such, TableView will automatically update whenever the teamMembers list changes. If the items list is available before the TableView is instantiated, it is possible to pass it directly into the constructor:TableView<Person> table = new TableView<>(teamMembers);At this point we now have a TableView hooked up to observe the teamMembers observableList. The missing ingredient now is the means of splitting out the data contained within the model and representing it in one or more TableColumn instances. To create a two-column TableView to show the firstName and lastName properties, we extend the last code sample as follows:TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");firstNameCol.setCellValueFactory(new PropertyValueFactory<>(members.get(0).firstNameProperty().getName())));TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");lastNameCol.setCellValueFactory(new PropertyValueFactory<>(members.get(0).lastNameProperty().getName())));table.getColumns().setAll(firstNameCol, lastNameCol);

说TableView<S>这个泛型代表的是table中每一列所存储的对象类型

就是说每一行作为一个对象,每一列是代表该对象所具有的属性,在给TableView初始化之后,要向TableView添加不同的列,添加TableColumn

然后就发现TableColumn<S, T>这个类有两个泛型,这个第一个S代表的就是和TableView一样的,这个T就是Type,代表该列所表示的数据类型。话不多说,上代码

/*** 先创建一个静态内部类* 作为TableView的行数据*/
public static class Person {private final StringProperty name;private final IntegerProperty age;private final StringProperty sex;private final StringProperty email;public Person(String name, int age, String sex, String email) {this.name = new SimpleStringProperty(name);this.age = new SimpleIntegerProperty(age);this.sex = new SimpleStringProperty(sex);this.email = new SimpleStringProperty(email);}public int getAge() {return age.get();}public String getEmail() {return email.get();}public String getName() {return name.get();}public String getSex() {return sex.get();}
}

然后就初始化TableView

//这个data是数据源
TableView<Person> table = new TableView<>(data);
//在写的时候也可以先初始化然后再设置数据源
TableView<Person> table = new TableView<>();
table.setItems(data);
//table可以可以作为成员变量

然后我们需要设置一个数据源

private final ObservableList<Person> data = FXCollections.observableArrayList(new Person("张三", 10, "男", "123123@qq.com"),new Person("李四", 90, "女", "123321@qq.com"),new Person("王富贵", 80, "男", "321123@qq.com")
);

这个是一个集合,用了观察者模式

观察者模式(Observer)又称发布-订阅模式(Publish-Subscribe:Pub/Sub)。它是一种通知机制,让发送通知的一方(被观察方)和接收通知的一方(观察者)能彼此分离,互不影响。

能够让表格实时监控数据的变化从而做出相应的改变

然后就是向表格中添加列

TableColumn<Person, String> nameCol = new TableColumn<>("姓名");
TableColumn<Person, String> ageCol = new TableColumn<>("年龄");
TableColumn<Person, String> sexCol = new TableColumn<>("性别");
TableColumn<Person, String> emailCol = new TableColumn<>("邮箱");

然后我们需要将列的对象和数据的属性进行绑定

nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
ageCol.setCellValueFactory(new PropertyValueFactory<>("age"));
sexCol.setCellValueFactory(new PropertyValueFactory<>("sex"));
emailCol.setCellValueFactory(new PropertyValueFactory<>("email"));

这个参数一定要是前面People类中所具有的属性

然后将这些列数据添加到TableView中

table.getColumns().addAll(nameCol, ageCol, sexCol, emailCol);

我们来看一下总的代码

public class Main extends Application {private static final TableView<Person> table = new TableView<Person>();private final ObservableList<Person> data = FXCollections.observableArrayList(new Person("张三", 10, "男", "123123@qq.com"),new Person("李四", 90, "女", "123321@qq.com"),new Person("王富贵", 80, "男", "321123@qq.com"));@Overridepublic void start(Stage stage) {//创建根面板BorderPane root = new BorderPane();Scene scene = new Scene(root, 500, 500);//创建表格的列TableColumn<Person, String> nameCol = new TableColumn<>("姓名");TableColumn<Person, String> ageCol = new TableColumn<>("年龄");TableColumn<Person, String> sexCol = new TableColumn<>("性别");TableColumn<Person, String> emailCol = new TableColumn<>("邮箱");//将表格的列和类的属性进行绑定nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));ageCol.setCellValueFactory(new PropertyValueFactory<>("age"));sexCol.setCellValueFactory(new PropertyValueFactory<>("sex"));emailCol.setCellValueFactory(new PropertyValueFactory<>("email"));//设置可编辑table.setEditable(true);//将列添加到TableView中table.getColumns().addAll(nameCol, ageCol, sexCol, emailCol);//设置数据源table.setItems(data);//将表格添加至根面板root.setCenter(table);//为舞台设置场景stage.setScene(scene);//场景显示stage.show();}public static void main(String[] args) {Application.launch(args);}//内部类public static class Person {private final StringProperty name;private final IntegerProperty age;private final StringProperty sex;private final StringProperty email;public Person(String name, int age, String sex, String email) {this.name = new SimpleStringProperty(name);this.age = new SimpleIntegerProperty(age);this.sex = new SimpleStringProperty(sex);this.email = new SimpleStringProperty(email);}public int getAge() {return age.get();}public String getEmail() {return email.get();}public String getName() {return name.get();}public String getSex() {return sex.get();}}}

结果图

 我们还可以设置列的属性能让表格可编辑(双击表格进入编辑状态)

nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
ageCol.setCellFactory(TextFieldTableCell.forTableColumn());
sexCol.setCellFactory(TextFieldTableCell.forTableColumn());
emailCol.setCellFactory(TextFieldTableCell.forTableColumn());

最后做个稍微高级一点的  美化一下

package testPack;import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;import java.util.Objects;/*** @author BLLGDZ* @data 2022-02-22 * @time 16:32* @version java - 17.0.1* @product_name IntelliJ IDEA* @Association: DMU* @E-mail: 670855120@qq.com* Right to use this code in any way you want without* warranty, support or any guarantee of it working*/
public class Main extends Application {private Scene scene = null;private final int WIDTH = 600;private final int HEIGTH = 600;private final Label label = new Label("TableViewTest");private final TableView<Person> table = new TableView<>();private final ObservableList<Person> data = FXCollections.observableArrayList();private final Button btnAdd = new Button("添加");private final Button btnDel = new Button("删除");private final TextField txtName = new TextField();private final TextField txtAge = new TextField();private final TextField txtSex = new TextField();private final TextField txtEmail = new TextField();private final TextField txtPhone = new TextField();private final TextField txtQQ = new TextField();@Overridepublic void start(Stage stage) {scene = new Scene(new BorderPane(), WIDTH, HEIGTH);initCSS();initComponents();initEvents();stage.setScene(scene);stage.show();}private void initComponents() {BorderPane root = (BorderPane) scene.getRoot();label.setPadding(new Insets(10, 0, 10, 0));//这个是我之前讲过的一种居中的方式 在前面的文章中有讲解,//利用HBox和VBox水平排列和垂直排列的特性将VBox和HBox相互嵌套能够打到居中的效果VBox vBox = new VBox();HBox hBox = new HBox();vBox.setAlignment(Pos.CENTER);hBox.setAlignment(Pos.CENTER);HBox inputBox = new HBox(10);inputBox.setAlignment(Pos.CENTER);inputBox.getChildren().addAll(txtName, txtAge, txtSex, txtEmail, txtPhone, txtQQ);inputBox.setPadding(new Insets(10, 10, 0, 10));HBox btnBox = new HBox(50);btnBox.setAlignment(Pos.CENTER);btnBox.getChildren().addAll(btnAdd, btnDel);btnBox.setPadding(new Insets(10, 10, 10, 10));txtAge.setTooltip(new Tooltip("填入年龄"));txtName.setTooltip(new Tooltip("填入姓名"));txtEmail.setTooltip(new Tooltip("填入邮箱"));txtSex.setTooltip(new Tooltip("填入性别"));txtPhone.setTooltip(new Tooltip("填入联系电话"));txtAge.setPromptText("年龄");txtName.setPromptText("姓名");txtEmail.setPromptText("Email");txtSex.setPromptText("性别");txtPhone.setPromptText("联系电话");txtQQ.setPromptText("QQ");TableColumn<Person, String> nameCol = new TableColumn<>("姓名");TableColumn<Person, Integer> ageCol = new TableColumn<>("年龄");TableColumn<Person, String> sexCol = new TableColumn<>("性别");TableColumn<Person, String> infoCol = new TableColumn<>("信息");TableColumn<Person, String> QQCol = new TableColumn<>("QQ");TableColumn<Person, String> phoneNumCol = new TableColumn<>("联系电话");nameCol.setMinWidth(100);ageCol.setMinWidth(100);sexCol.setMinWidth(100);QQCol.setMinWidth(130);phoneNumCol.setMinWidth(130);infoCol.getColumns().addAll(QQCol, phoneNumCol);nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));ageCol.setCellValueFactory(new PropertyValueFactory<>("age"));sexCol.setCellValueFactory(new PropertyValueFactory<>("sex"));QQCol.setCellValueFactory(new PropertyValueFactory<>("QQnum"));phoneNumCol.setCellValueFactory(new PropertyValueFactory<>("phoneNum"));table.setItems(data);table.getColumns().addAll(nameCol, ageCol, sexCol, infoCol);vBox.getChildren().addAll(label, table, inputBox, btnBox);hBox.getChildren().add(vBox);root.setCenter(hBox);}private void initEvents() {Alert alert = new Alert(Alert.AlertType.INFORMATION);btnAdd.setOnAction(e -> {//验证表单(我就做个简单的验证非空了  剩下什么邮箱姓名电话格式这些东西,大家自己努力把 一堆正则表达式)if (txtName.getText().isEmpty()|| txtSex.getText().isEmpty()|| txtPhone.getText().isEmpty()|| txtEmail.getText().isEmpty()|| txtAge.getText().isEmpty()) {alert.setContentText("表格未填满!");alert.show();return;}data.add(new Person(txtName.getText(), Integer.parseInt(txtAge.getText()), txtSex.getText(), txtEmail.getText(), txtQQ.getText(), txtPhone.getText()));});btnDel.setOnAction(e -> {if (data.size() == 0) {alert.setContentText("表格为空!");alert.show();return;}int moveIndex = table.getSelectionModel().getFocusedIndex();System.out.println(moveIndex);data.remove(moveIndex);});}private void initCSS() {BorderPane root = (BorderPane) scene.getRoot();//懒了  就这么写了String txt = """-fx-background-radius: 20px;-fx-background-color: rgba(0, 0, 0, .3);-fx-text-fill: white;-fx-pref-height: 25px;""";String backgroundColor = """-fx-background-color: #91B493;""";String table_backgroundColor = """-fx-background-color: #4B4E2A;""";String label = """-fx-font-size: 20px;-fx-text-fill: white;-fx-font-weight: bold;""";String btn = """-fx-background-color: #904840;-fx-background-radius: 20px;-fx-text-fill: white;-fx-pref-width: 100px;-fx-pref-height: 30px;""";txtEmail.setStyle(txt);txtQQ.setStyle(txt);txtName.setStyle(txt);txtSex.setStyle(txt);txtPhone.setStyle(txt);txtAge.setStyle(txt);root.setStyle(backgroundColor);this.label.setStyle(label);btnDel.setStyle(btn);btnAdd.setStyle(btn);this.table.setStyle(table_backgroundColor);}public static void main(String[] args) {Application.launch(args);}public static class Person {private final StringProperty name;private final IntegerProperty age;private final StringProperty sex;private final StringProperty email;private final StringProperty QQnum;private final StringProperty phoneNum;public Person(String name, int age, String sex, String email, String QQnum, String phoneNum) {this.name = new SimpleStringProperty(name);this.age = new SimpleIntegerProperty(age);this.sex = new SimpleStringProperty(sex);this.email = new SimpleStringProperty(email);this.QQnum = new SimpleStringProperty(QQnum);this.phoneNum = new SimpleStringProperty(phoneNum);}public int getAge() {return age.get();}public String getEmail() {return email.get();}public String getName() {return name.get();}public String getSex() {return sex.get();}public String getPhoneNum() {return phoneNum.get();}public String getQQnum() {return QQnum.get();}}}

效果图:(实属有点丑  但是还是对付看吧)

对了推荐大家一个选色的网址   这个NIPPON COLORS - 日本の伝統色可以在里面找喜欢的颜色

 看我这么可怜,给我点个赞吧


http://chatgpt.dhexx.cn/article/EuXmkrn9.shtml

相关文章

Qt4实现TableView显示表格数据

最近又开始搞QT开发了&#xff0c;前面学的MVC啥的都忘得差不多了&#xff0c;重新整理一遍思路吧。 目前的需求是&#xff1a;读取文本文件&#xff0c;表格型数据&#xff0c;用tableview显示出来&#xff0c;最后画图。这涉及到三个问题&#xff0c;文件读写&#xff0c;数…

NAT模式下的虚拟机网络配置

原理 NAT模式&#xff0c;也叫地址转换模式&#xff0c; 当把我们的虚拟机的上网方式设置为NAT模式时&#xff0c;虚拟机、宿主机、各网卡之间的连接关系可用下图来表示&#xff1a; 具体配置流程 1 将本地以太网共享到v8适配器上 2 查看虚拟网络编辑中的NAT模式下的子网IP…

虚拟机vmware设置nat模式上网

桥接模式上网&#xff1a;虚拟机vmware设置桥接模式上网_cao849861802的博客-CSDN博客 首先虚拟机有两个虚拟网卡vmnet0和vmnet8 这个vmnet0默认的是桥接模式&#xff0c;这个vmnet8默认是nat模式&#xff1b; 我们这里只看nat模式&#xff0c;所以先不关心vmnet0虚拟网卡&a…

VMware16NAT模式配置固定IP

文章目录 前言一、NAT配置固定IP二、重启网卡结尾 前言 为什么要配置固定IP呀&#xff1f;这个很容易解释啊&#xff0c;因为配置集群要设置固定IP&#xff08;主结点需要管理子结点&#xff0c;通过固定IP识别机器&#xff09;&#xff0c;因为你访问虚拟机方便&#xff08;不…

VMware Workstation中桥接模式、NAT模式、仅主机模式

一、VMware虚拟机的网络模式 VMware工作站虚拟机有三种网络模式【①桥接模式 ②NAT模式 ③仅主机模式】,如下图所示: 二、VMware虚拟机的网络模式介绍 2.0、VMware的虚拟设备 VMware的虚拟设备 序号虚拟设备编号说明1VMnet0是虚拟桥接网络下的虚拟交换机2VMnet1是虚拟Host-…

vm虚拟机nat模式配置

痛点&#xff1a; 为了解决虚拟机与板子网络的调试的问题&#xff0c;我之前一直用桥接&#xff0c;如果虚拟机想上网就桥接到无线网卡&#xff0c;如果想连接板子&#xff0c;就桥接到有线网卡&#xff0c;麻烦&#xff0c;需要来回切换&#xff0c;还有就是不插板子的情况下和…

nat模式

原文链接&#xff1a;https://www.linuxidc.com/Linux/2016-09/135521p2.htm &#xff08;复制过来只是为了学习方便&#xff0c;如有不妥会立即删除&#xff09; 二、NAT&#xff08;地址转换模式&#xff09; 刚刚我们说到&#xff0c;如果你的网络ip资源紧缺&#xff0c;但…

虚拟机NAT模式无法联网

工作中遇到NAT模式虚拟机&#xff0c;修改了编辑-虚拟网络编辑器 中NAT设置IP&#xff0c;DNS&#xff0c;DHCP等配置&#xff0c;在centos8中修改了ens33文件都无法联网的情况&#xff0c;特此总结解决方案 按照该方法尝试后无效&#xff08;解决方法在下面&#xff09; 第一…

桥接模式NAT模式 详解

NAT模式 和 桥接模式 网络地址转换 NAT &#xff1a; 首先看一下NAT的概念&#xff1a;装有NAT软件的路由器叫做NAT路由器&#xff0c;它至少有一个有效的外部全球IP地址&#xff0c;这样所有使用本地地址&#xff08;内部专用地址&#xff09;的主机在和外界通信时&#xff…

虚拟机NAT模式无法上网

虚拟机NAT模式无法上网 一、确认虚拟机的ip地址二、确认服务是否开启 一、确认虚拟机的ip地址 确认虚拟机的ip地址与本机的vmnet8的ip地址是否在同一个网段&#xff0c;且网关是否一致&#xff1a; cd /etc/sysconfig/network-scripts/ ls vi ifcfg-ens33如果ip配置都没有问…

【VMware】NAT模式、桥接模式、仅主机模式

VMware的NAT模式、桥接模式、仅主机模式 转载自&#xff1a;https://wxler.github.io/2021/02/02/221724/ 1. NAT模式 拓扑图&#xff1a; 在NAT网络中&#xff0c;会用到VMware Network AdepterVMnet8虚拟网卡。 VMware Network AdepterVMnet8是主机上的一块虚拟网卡&…

虚拟机NAT模式集群改为桥接模式集群

有时候&#xff0c;A 电脑要访问 B 电脑上安装的虚拟机&#xff0c;尴尬的是之前虚拟机配置的网络连接模式为 NAT 模式。 那怎么才能让 A 电脑正常地访问 B 电脑上的虚拟机呢&#xff1f;就需要将虚拟机的网络连接模式由 NAT 模式修改为 桥接模式 。 需要下面简单的几步就可以…

LVS NAT模式配置实践

1. LVS单网卡配置 注&#xff1a;实际应用中LVS使用双网卡&#xff0c;这里仅做演示用。架构图如下&#xff1a; 单网卡LVS 1.1 机器信息 LVS LVS&#xff1a;eth0 10.10.1.100&#xff08;VIP&#xff09; Real Server RS1&#xff1a;eth0 10.10.1.1RS2&#xff1a;eth…

虚拟机网络模式-NAT模式配置

1、打开VMware&#xff0c;点击编辑——》虚拟网络编辑器 2、配置NAT子网。 注意&#xff1a;不能配置和物理主机为同一网段的IP段 点击NAT设置。设置虚拟子网的网关 注意&#xff1a;正常是使用.1做为网关&#xff0c;如果出现网络不行&#xff0c;可以改成.2做网关 4、点击…

Linux下配置nat模式

&#xff08;一&#xff09;打开网络虚拟编辑器 点击更改设置&#xff0c;我们安装好VMware后&#xff0c;在网络连接处会出现两张虚拟网卡&#xff0c;分别是vmnet1和vmnet8&#xff0c;net模式需要配置vmnet8网卡。 接下来通过命令进入 cd /etc/sysconfig/network-scripts&am…

Vmware配置NAT模式

NAT模式注意事项 1.虚拟网卡要和虚拟机在一个网段内。 2.虚拟网卡的网关要和虚拟机网关相同。 3.虚拟机网卡的子网和物理主机不需要在同一个网段&#xff0c;物理主机网段一般为192.168.1.xx,建议虚拟机使用别的网段。 NAT模式使用的是VMnet8虚拟网卡配置 虚拟网络编辑器配置…

【虚拟机NAT模式及桥接模式配置】

VMware虚拟机网络配置 虚拟机常见的网络类型NAT&#xff08;网络地址转换&#xff09;Bridged&#xff08;桥接模式&#xff09;Host-Only&#xff08;仅主机&#xff09; 虚拟机网络配置配置为NAT模式配置为桥接模式 虚拟机常见的网络类型 Vmware 为我们提供了三种网络工作模…

centos 设置nat模式

1&#xff1a;将虚拟机的网络适配器设置为nat模式 2&#xff1a;在vm的编辑菜单中选中虚拟网络编辑器&#xff0c;选择更改设置&#xff0c;进去后选中VMnet8&#xff0c; 3&#xff1a;在虚拟机中进入/etc/sysconfig/network-scripts目录&#xff0c;修改ifcfg-eth33文件 4:宿…

NAT模式 桥接模式bridge原理理解

桥接场景 无论现在的各种容器&#xff0c;还是我们之前常用的虚拟机&#xff0c;为了与局域网内其他IP通讯通常需要用到『桥接』。 Bridge桥接方式 Bridge 将虚拟机桥接到host机器的网卡上,guest和host机器都通过bridge上网.对外不同的ip。 NAT 想要理解Bridge首先要理解NA…

VMware虚拟机 之 NAT模式详解

如果你的网络ip资源紧缺&#xff0c;但是你又希望你的虚拟机能够联网&#xff0c;这时候NAT模式是最好的选择。NAT模式借助虚拟NAT设备和虚拟DHCP服务器&#xff0c;使得虚拟机可以联网。其网络结构如下图所示&#xff1a; 在NAT模式中&#xff0c;主机网卡直接与虚拟NAT设备相…