JavaFX控件——TableView

本文详细介绍了JavaFX中的TableView控件,包括如何创建表格、定义数据模型、添加新行、实现列数据排序和编辑功能。通过示例代码展示了如何使用TableView创建地址簿应用,演示了如何使用ObservableList绑定数据,以及如何处理单元格编辑和Map数据的展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在JavaFX 应用中对创建表格最重要的是TableView, TableColumnTableCell这三个类。

你可以通过实现数据模型(data model) 和 实现 单元格工厂(cell factory) 来填充表格。

表格类提供了表格列嵌入式的排序能力和必要时调整列宽度的功能。
下面开始学习表格类的相关内容。

创建一个表格

例子1-1
import javafx.application.Application;  
import javafx.geometry.Insets;  
import javafx.scene.Group;  
import javafx.scene.Scene;  
import javafx.scene.control.Label;  
import javafx.scene.control.TableColumn;  
import javafx.scene.control.TableView;  
import javafx.scene.layout.VBox;  
import javafx.scene.text.Font;  
import javafx.stage.Stage;  

public class TableViewSample extends Application {
   
     

    private TableView table = new TableView();  
    public static void main(String[] args) {  
        launch(args);  
    }  

    @Override  
    public void start(Stage stage) {  
        Scene scene = new Scene(new Group());  
        stage.setTitle("Table View Sample");  
        stage.setWidth(300);  
        stage.setHeight(500);  

        final Label label = new Label("Address Book");  
        label.setFont(new Font("Arial", 20));  

        table.setEditable(true);  

//设置自动拉满    table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);

        TableColumn firstNameCol = new TableColumn("First Name");  
        TableColumn lastNameCol = new TableColumn("Last Name");  
        TableColumn emailCol = new TableColumn("Email");  

        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);  

        final VBox vbox = new VBox();  
        vbox.setSpacing(5);  
        vbox.setPadding(new Insets(10, 0, 0, 10));  
        vbox.getChildren().addAll(label, table);  

        ((Group) scene.getRoot()).getChildren().addAll(vbox);  

        stage.setScene(scene);  
        stage.show();  
    }  
} 

此表格组件 通过实例化TableView类来创建。

在该例子中,表格组件被添加到VBox 的布局容器中,然而你也可以直接将其添加到应用场景中。

例子 12-1定义了3列将用来存放地址簿的信息:一个联系人的 姓和名以及电子邮箱地址。列通过TableColumn这个类创建。

TableViewgetColumns方法可以获取之前创建过的列。在你的应用中,你可以用此方法动态的添加和移除表格列。

编译并运行此程序将获取输入输出 ,结果如图所示:

你可以通过setVisible 方法来控制列是否显示。

如:如果你的应用逻辑需要隐藏电子邮件地址,可以这样做:emailCol.setVisible(false).
将这句代码添加到例子1-1中,效果如图:

如果你的数据需要更加复杂的呈现方式,你可以创建嵌套列
假设地址簿中的联系方式有两个电子邮箱账户。你需要两列来分别呈现第一个和第二个电子邮箱地址。
像下面代码中展示的一样,创建两个子列,然后调用emailColgetColumns方法

TableColumn firstEmailCol = new TableColumn("Primary");  
TableColumn secondEmailCol = new TableColumn("Secondary");  

emailCol.getColumns().addAll(firstEmailCol, secondEmailCol);  

在这段代码里面添加到例子1-1中然后编译并运行, 此表格将呈现下图中的样子.
带有嵌套列的表格
尽管表格已经添加到应用中,但是因为表格中没有数据,标准的标题“表中无内容”(表格内容为空)将呈现在表格中。

如果不想显示上述标题,你可以使用setPlaceholder 方法类制定 一个 Node(节点)对象呈现在空表格中。

定义数据模型( Data Model)

当你要在JavaFx应用中创建一个表格,最好先创建一个类来定义数据模型和提供将来和表格交互的方法和属性。例子1-2中定义了Person类来定义数据和地址簿。

例字1-2 创建 Person 类
public class Person {  
    private final SimpleStringProperty firstName;  
    private final SimpleStringProperty lastName;  
    private final SimpleStringProperty email;  

    private Person(String fName, String lName, String email) {  
        this.firstName = new SimpleStringProperty(fName);  
        this.lastName = new SimpleStringProperty(lName);  
        this.email = new SimpleStringProperty(email);  
    }  

    public String getFirstName() {  
        return firstName.get();  
    }  
    public void setFirstName(String fName) {  
        firstName.set(fName);  
    }  

    public String getLastName() {  
        return lastName.get();  
    }  
    public void setLastName(String fName) {  
        lastName.set(fName);  
    }  

    public String getEmail() {  
        return email.get();  
    }  
    public void setEmail(String fName) {  
        email.set(fName);  
    }  

}  

firstName, lastName, 和 email这些字符串属性用来提供特殊数据元素的引用。

另外,每个数据元素都提供了getset方法。 这样如果调用 getFirstName方法经返回firstName属性的值,可以通过调用setFirstName方法来为这个属性赋值 。

在数据模型已经在Person 类中呈现以后。你可以创建ObservableList 数组随心所欲的定义数据行(data rows) 在你的表格中展示
下面的代码片段实现了这个任务:

final ObservableList<Person> data = FXCollections.observableArrayList(  
    new Person("Jacob", "Smith", "jacob.smith@example.com"),  
    new Person("Isabella", "Johnson", "isabella.johnson@example.com"),  
    new Person("Ethan", "Williams", "ethan.williams@example.com"),  
    new Person("Emma", "Jones", "emma.jones@example.com"),  
    new Person("Michael", "Brown", "michael.brown@example.com")  
); 

下一步就是将这些数据和表格的列之间建立联系。你可以像例子1-3中那样通过对每个数据元素的属性定义来实现。

例子1-3 为列创建数据属性
firstNameCol.setCellValueFactory(  
    new PropertyValueFactory<Person,String>("firstName")  
);  
lastNameCol.setCellValueFactory(  
    new PropertyValueFactory<Person,String>("lastName")  
);  
emailCol.setCellValueFactory(  
    new PropertyValueFactory<Person,String>("email")  
);  

setCellValueFactory 方法为每个列定制单元工厂。单元工程通过使用PropertyValueFactory类来实现, 表格列的firstName, lastNameemail 属性来引用Person中相应的属性的 。

当数据模型已经定义完毕,数据已经添加并关联到对应的列,你还可以通过TableViewsetItems 方法来添加表格数据:table.setItems(data).

因为ObservableList 对象能够跟踪表格元素的任何变化,当其中的数据变化,TableView 的内容也自动更新。

例子1-4 创建一个表格并添加数据
import javafx.application.Application;  
import javafx.beans.property.SimpleStringProperty;  
import javafx.collections.FXCollections;  
import javafx.collections.ObservableList;  
import javafx.geometry.Insets;  
import javafx.scene.Group;  
import javafx.scene.Scene;  
import javafx.scene.control.Label;  
import javafx.scene.control.TableColumn;  
import javafx.scene.control.TableView;  
import javafx.scene.control.TextField;  
import javafx.scene.control.cell.PropertyValueFactory;  
import javafx.scene.layout.VBox;  
import javafx.scene.text.Font;  
import javafx.stage.Stage;  

public class TableViewSample extends Application {
   
     

    private TableView<Person> table = new TableView<Person>();  
    private final ObservableList<Person> data =  
        FXCollections.observableArrayList(  
            new Person("Jacob", "Smith", "jacob.smith@example.com"),  
            new Person("Isabella", "Johnson", "isabella.johnson@example.com"),  
            new Person("Ethan", "Williams", "ethan.williams@example.com"),  
            new Person("Emma", "Jones", "emma.jones@example.com"),  
            new Person("Michael", "Brown", "michael.brown@example.com")  
        );  

    public static void main(String[] args) {  
        launch(args);  
    }  

    @Override  
    public void start(Stage stage) {  
        Scene scene = new Scene(new Group());  
        stage.setTitle("Table View Sample");  
        stage.setWidth(450);  
        stage.setHeight(500);  

        final Label label = new Label("Address Book");  
        label.setFont(new Font("Arial", 20));  

        table.setEditable(true);  

        TableColumn firstNameCol = 
### JavaFX实现 TableView 组件的动态数据更新 在 JavaFX 应用程序中,`TableView` 的动态数据更新主要依赖于 `ObservableList` 和属性绑定机制。通过这种方式可以确保当底层数据模型发生改变时,表格视图能够自动反映这些更改。 #### 使用 ObservableList 进行动态加载和刷新 为了使 `TableView` 可以响应数据的变化并及时更新显示的内容,应该使用 `ObservableList<T>` 来存储表中的项目列表。每当向此集合添加、移除或者修改元素的时候,都会触发相应的事件通知给监听器,从而促使界面重新渲染受影响的部分[^2]。 ```java // 创建一个可观察的数据集 private final ObservableList<Person> data = FXCollections.observableArrayList( new Person("Jacob", "Smith"), new Person("Isabella", "Johnson") ); tableView.setItems(data); ``` #### 数据绑定与 POJO 改造 为了让 `TableView` 更加智能化地处理来自业务逻辑层的信息变动,通常会对原有的简单 Java Bean 类型做一定调整——即采用封装了特定 getter/setter 方法以及实现了 `PropertyChangeListener` 接口的新类结构来替代之。这样做不仅有助于简化代码编写过程,更重要的是能有效支持双向绑定特性,在任何一处位置上发生的变更都可以迅速传播至其他关联区域。 对于每一个需要展示在其上的字段而言,则需设置合适的单元格工厂 (`cellValueFactory`) ,以便正确提取出对应实体对象内部的相关信息片段作为最终呈现出来的文本字符串: ```java firstNameColumn.setCellValueFactory(new PropertyValueFactory<>("firstName")); lastNameColumn.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty()); ``` 这里展示了两种不同的方式去指定列所代表的具体含义;前者利用反射技术直接读取公共成员变量名称完成映射关系建立工作,而后者则是借助表达式语言显式指定了访问路径达到相同目的的同时还允许进一步定制化操作比如格式转换等额外功能扩展[^1]。 #### 完整示例代码 下面给出一段完整的演示样例用于说明上述概念的实际应用情况: ```java import javafx.application.Application; import javafx.beans.property.SimpleStringProperty; import javafx.collections.FXCollections; import javafx.scene.Scene; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.stage.Stage; public class TableViewExample extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) throws Exception{ // 初始化 Table View 控件及其各组成部分定义 TableView<Person> tableView = new TableView<>(); TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name"); firstNameCol.setMinWidth(100); firstNameCol.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty()); TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name"); lastNameCol.setMinWidth(100); lastNameCol.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty()); // 将两列加入到表格之中形成完整布局形式 tableView.getColumns().addAll(firstNameCol, lastNameCol); // 构建初始状态下的人员记录条目清单供后续填充表格内容使用 ObservableList<Person> people = FXCollections.observableArrayList(); people.add(new Person("John", "Doe")); // 把准备好的观测者模式下管理的对象数组赋值给目标控件实例 tableView.setItems(people); Scene scene = new Scene(tableView, 400, 300); primaryStage.setScene(scene); primaryStage.show(); // 模拟异步任务完成后追加新纪录的情形 Thread.sleep(2000); // 延迟执行模拟网络请求或其他耗时动作 Platform.runLater(() -> { people.add(new Person("Jane", "Roe")); // 更新UI线程安全的方式新增一条数据项 }); } } class Person { private SimpleStringProperty firstName; private SimpleStringProperty lastName; public Person(String fName, String lName){ this.firstName = new SimpleStringProperty(fName); this.lastName = new SimpleStringProperty(lName); } public String getFirstName() {return firstName.get();} public void setFirstName(String value){this.firstName.set(value);} public String getLastName(){return lastName.get();} public void setLastName(String value){this.lastName.set(value);} public SimpleStringProperty firstNameProperty(){ return firstName; } public SimpleStringProperty lastNameProperty(){ return lastName; } } ``` 这段代码创建了一个简单的应用程序窗口,其中包含两个名为 “First Name” 和 “Last Name”的列,并初始化了一些测试数据。之后通过休眠主线程一段时间再唤醒它来进行一次新的插入操作以此验证整个流程是否正常运作良好。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值