DOC-03-13 表格视图(TableView)

在本章中,你将学习如何在JavaFX应用程序中使用表格,例如创建表格、用为表格填充数据、编辑表格行。

在JavaFX SDK API中有类被设计用于以表格形式展现数据的类。其中最重要的类是TableView、TableColumn和TableCell。你可以通过实现数据模型(data model)以及提供单元格工厂(cell factory)来来填充表格。

表格相关类内置提供了对表格列数据排序、自动调整列宽功能。

图13-1展现了一个典型的表格,它展示了一个地址簿中的联系人信息。

13-1 表格样例

3-13-1 table-sample

创建一个表格

下面的代码创建一个包含三列的空表格,并将其添加到应用程序场景(scene)中。

通过实例化TableView类来创建表格控件。在上例中将表格添加到了VBox布局中,然而你也可以直接将其添加到scene中。

在上例中添加了3列用于存储地址簿中的下列信息:联系人的姓、名和电子邮件。通过使用TableColumn类来创建列。

TableView的getColumns方法将前面创建的列添加到表格中。在你的应用程序中,你可以用它来动态添加和移除列。

上面的程序编译并运行后将会看到如下图所示的界面:

13-2 空表格

3-13-2 table-empty

你可以通过setVisible方法来管理列的可见性。例如需要隐藏电子邮件信息列,你可以通过emailCol.setVisible(false)来实现。

当你的数据结构需要更复杂的表现形式时,你还可以创建嵌套列。

例如,如果地址簿中需要两个电子邮件,那么你需要两列来分别表示主邮件地址和辅邮件地址。创建两个子列,然后仿照下面的例子来调用emailCol的getColumns方法:

在前面的样例代码中添加这三句代码后,编译运行程序的结果将如图13-2:

13-3 带有嵌套列的表格

3-13-3 table-nested

尽管在应用程序中添加了表格,但是由于尚未定义数据,因此只能看到提示“表中无内容”的标准提示信息。如果需要替换此提示信息,你可以使用setPlaceholder方法指定一个Node对象来用于当表格为空时进行提示。

定义数据模型(Data Model

当你在JavaFX应用程序中创建表格时,一个最佳实践是:创建一个类用于定义数据模型并且提供方法和属性。下面的样例创建了一个Person类用于定义地址簿中的数据。

字符串属性firstName、lastName和email都分别对应着一个特定的数据元素。

另外,每个数据元素都提供了get和set方法,例如getFirstName方法将返回firstName属性值,而setFirstName方法将指定对应的属性值。

当使用Person类来说明数据模型之后,你可以通过创建ObservableList数组来定义希望在表格中展现的数据行。下面的样例代码将展示如何实现此任务:

下一步则是将数据关联到表格中的列。你可以通过为每个数据元素定义属性来完成此操作,样例代码如下:

setCellValueFactory方法为每列指定了一个单元格工厂(cell factory),这些cell factory是通过PropertyValueFactory类来实现的,它将Person类中对应的属性映射到对应的表格列中。

当数据模型被定义完毕,并且数据被关联到列之后,你可以通过TableView类的setItems方法来向表格中添加数据:如:table.setItems(data)。

由于ObservableList对象具有自动追踪其包含元素的改变的功能,所以TableView的内容将会在数据改变时自动更新。

尝试下面的代码:

这段样例代码的执行结果如图13-4:

13-4 填充了数据的表格

3-13-4 table-data

增加新行

在上面的例子中,表格内有5行数据,目前这些数据无法被修改。

你可以使用文本框来输入新的姓名和邮件地址信息。TextField控件允许你的应用程序接收来自用户的输入。下面的例子中创建了三个文本框,并且为每个文本框定义了提示信息,并且添加了“Add”按钮。

当用户点击“Add”按钮时,输入到文本框中的值将会通过Person的构造方法设置到数据中,然后增加到变量data对应的ObservableList中。因此,你会看到在表格中出现一行新的信息。

尝试运行下面的样例代码:

这个程序没有提供过滤器来对输入信息进行格式校验,例如:输入一个错误格式的电子邮件地址。你可以在开发自己的应用程序时提供此功能。

目前的样例程序也没有对空值进行校验。如果没有输入任何值,当点击“Add”按钮时,将会在表格中添加一个空行。

图13-5展示了用户如何添加新的数据行:

13-5 向地址簿添加联系人信息

3-13-5 table-add

图13-6展现了点击“Add”按钮之后的表格。Emma White的联系信息现在出现在表格之中了。

13-6 新增表数据项

3-13-6 table-added

对列中的数据排序

TableView类内置提供了对列数据排序的功能。用户可以通过单击列头来改变数据顺序。第一次点击将会升序排列,第二次会降序排列,第三次则会取消对该列排序。默认情况下不会对任何一列进行排序。

用户可以对表格中的多列数据同时进行排序,并能指定每一列在排序中的优先级。如果要进行多列排序,只需要在在点击列头的同时按住Shift键即可。

在图13-7中,FirstName被升序排列,Last Name被降序排列。注意其中第一列的优先级比第二列的优先级高。

13–7对多列进行排序

3-13-7 table-sort

作为开发者,你可以通过setSortType方法来为每一列设置排序特性。你可以指定升序和降序类型。例如,使用下面的代码行可以将emailCol列设置为降序:

通过向TableView.sortOrder observable list中增加或移除TableColumn对象,你也可以指定哪些列需要排序。在此list中的列顺序表示排序的优先级(例如,排在第0位的列比排在第1位的列具有更高的排序优先级)

如果要禁用数据排序特性,可在列上调用setSortable(false)方法。

编辑表格中的数据

TableView类不仅仅可以展现表格数据,并且提供了编辑功能。使用setEditable方法来启用对表格内容的编辑。

使用setCellFactory方法来重新实现表格的单元格,使用TextFieldTableCell类来使其变成一个文本域。setOnEditCommit方法处理编辑过程,并且将更新后的值分配给对应的表格单元格。下面的样例代码展示如何来使用这些方法对First Name、Last Name和Email列进行编辑。

13–9 实现单元格编辑

下面是完整代码:

下图中用户正在编辑Michael Brown的信息。为了编辑单元格,用户在单元格中输入了新值,然后按下回车键。对应的单元格在按下回车之前不会被修改。相关的行为由TextField类的实现方式决定。

13–8 编辑表格单元格

3-13-8 table-edit

注意TextField控件默认实现的行为是在用户按下回车键后提交对内容的编辑。你可以重新定义TextField的行为使其在失去焦点时提交对内容的编辑,这是一个较为常见的用户体验需求。下面的样例代码提供了对应的示例。

13–11 单元格编辑的另一种解决方案

注意这种实现方式在将来的版本中可能会变得多余,因为TextFieldTableCell实现类会逐步提供更好的用户体验。

添加Map数据到表格中

你可以向表格增加Map数据。在下列中使用MapValueFactory类来展示student的ID map。

13–12添加Map数据到表格中

MapValueFactory类实现了Callback接口,并且进行了特殊设计以便用于表格列单元格工厂。在上面的例子中dataRow hash Map表示了TableView对象中的一行。在Map中有两个String Key :Column1MapKey和Column2MapKey分别将对应的值映射到第一列和第二列。setCellValueFactory方法用与key值对应的数据来填充列,因此第一列会包含与“A”对应的数据,而第二列包含与“B”对应的数据。

样例程序运行后效果如下图:

13-9 带有Map数据的表格视图

3-13-9 table-map

在JavaFX中列表数据展示控件有一个更为强大的扩展控件:TreeTableView。可参考树表视图(Tree Table)章节获取更多相关信息。

相关的API文档

    · TableView

    · TableColumn

    · TableCell

    · TextField

    · TextFieldTableCell

    · TreeTableView

    · MapValueFactory

    · Button       

打赏一下
支付宝
微信
除非注明,博客文章均为原创,转载请标明文章地址
本文地址: http://www.javafxchina.net/blog/2015/04/doc03_tableview/
百度已收录