声明:如需转载,请注明出处:http://blog.csdn.net/originer
在本章中,你将会创建一个地址簿应用程序,其中包括一个带有姓名和邮件地址的表格。本教程展示了如何操作带有数据的表格,包括数据排序,单元格中的数据对齐,向表格内增加行。
在开始之前,我们假定你对FXML相关的一些知识有了相当的了解,至少你已经完成了官方文档中的“开始JavaFX之旅”(“Getting Started”)系列课程,尤其对于下列知识点你必需已经掌握:
- FXML工程的基本架构(.java,jfxml和控制类)
- 如何在IDE中创建和运行JavaFXFXML工程
- 关于布局(layout)和控件的基本知识
在你开始这个教程之前,确保IDE版本支持对应版本的JavaFX(译者注:包括要支持Java8)
创建工程
在IDE中创建工程,在其中创建FXMLTableView.java、FXMLTableViewController.java、fxml_tableview.fxml三个文件。注意如果是使用NetBeansIDE来创建的,则需要创建FXMLTableView工程,并重命名其中对应的文件。现在FXMLTableView类的代码如下:
public class FXMLTableView extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("FXML TableView Example");
Pane myPane = (Pane)FXMLLoader.load(getClass().getResource
("fxml_tableview.fxml"));
Scene myScene = new Scene(myPane);
primaryStage.setScene(myScene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
注意目前Java类中并没有包括创建场景的相关代码。在教程的下一部分会告诉你如何在FXML文件中来创建场景。
创建基本的用户界面
现在开始创建用户界面,先创建一个GridPane布局容器作为场景的根节点。然后增加一个Label和TableView控件作为其子节点。
1. 将fxml_tableview.fxml文件内容改为下面的内容:
<GridPane alignment="CENTER" hgap="10.0" vgap="10.0"
xmlns:fx="http://javafx.com/fxml"
fx:controller="fxmltableview.FXMLTableViewController">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</GridPane>
2. 向GridPane layout布局容器中增加Label和TableView,代码如下:
<GridPane alignment="CENTER" hgap="10.0" vgap="10.0"
xmlns:fx="http://javafx.com/fxml"
fx:controller="fxmltableview.FXMLTableViewController">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</padding>
<strong><Label style="-fx-font: NORMAL 20 Tahoma;" text="Address Book"
GridPane.columnIndex="0" GridPane.rowIndex="0">
</Label>
<TableView fx:id="tableView" GridPane.columnIndex="0"
GridPane.rowIndex="1">
</TableView></strong>
</GridPane>
3. 增加Inset类的import语句
<?import javafx.geometry.Insets?>
运行程序,你将会看到看到一个带有文本“Address Book”的Label以及一个带有文本“No columns in table”的表格,如下图:
增加表格中的列
使用TableColumn类来在表格中增加3列,分别用于显示数据:First Name,Last Name以及Email Address。代码如下:
<TableView fx:id="tableView" GridPane.columnIndex="0" GridPane.rowIndex="1">
<strong> <columns>
<TableColumn text="First Name">
</TableColumn>
<TableColumn text="Last Name">
</TableColumn>
<TableColumn text="Email Address">
</TableColumn>
</columns></strong>
</TableView>
参考API文档可获取更多信息。
下图展现了运行效果:
定义数据模型
package fxmltableview;
import javafx.beans.property.SimpleStringProperty;
public class Person {
private final SimpleStringProperty firstName = new SimpleStringProperty("");
private final SimpleStringProperty lastName = new SimpleStringProperty("");
private final SimpleStringProperty email = new SimpleStringProperty("");
public Person() {
this("", "", "");
}
public Person(String firstName, String lastName, String email) {
setFirstName(firstName);
setLastName(lastName);
setEmail(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);
}
}
将数据与表格关联
下面定义每一行的数据,并将其关联到表格。
1. 在fxm_tableview.fxml文件中,创建一个ObservableList列表并定义一些希望展现在表格中的数据,在</columns>和 </TableView>标签之间添加代码,样例代码如下:
</columns>
<items>
<strong><FXCollections fx:factory="observableArrayList">
<Person firstName="Jacob" lastName="Smith"
email="jacob.smith@example.com"/>
<Person firstName="Isabella" lastName="Johnson"
email="isabella.johnson@example.com"/>
<Person firstName="Ethan" lastName="Williams"
email="ethan.williams@example.com"/>
<Person firstName="Emma" lastName="Jones"
email="emma.jones@example.com"/>
<Person firstName="Michael" lastName="Brown"
email="michael.brown@example.com"/>
</FXCollections></strong>
</items>
</TableView>
2. 为每列指定一个cell factory来关联数据,代码如下:
<columns>
<TableColumn text="First Name">
<strong> <cellValueFactory><PropertyValueFactory property="firstName" />
</cellValueFactory></strong>
</TableColumn>
<TableColumn text="Last Name">
<strong><cellValueFactory><PropertyValueFactory property="lastName" />
</cellValueFactory></strong>
</TableColumn>
<TableColumn text="Email Address">
<strong> <cellValueFactory><PropertyValueFactory property="email" />
</cellValueFactory></strong>
</TableColumn>
</columns>
3. 引入需要的包
<?importjavafx.scene.control.cell.*?>
<?importjavafx.collections.*?>
<?import fxmltableview.*?>
(译者注:第三行注意需要根据实际情况调整,因为有可能你创建的项目的包名不是fxmltableview)
下图展现了此时程序的运行情况:
此时你可以尝试TableView类的一些内置的功能特点:
- 通过拖放列头分隔线来改变列宽
- 通过拖放列头来改变列的顺序
- 通过单击列头来根据列数据进行排序。第一次单击进行升序排列、第二次按降序排列、第三次恢复默认情况不再排序。默认情况下是不会进行排序的。
在启动时排序
在本节中将进行排序顺序的设置,使得First Name列在应用启动时按字母升序排列。首先需要为对应的列创建一个ID,然后创建一个reference来应用它。
1.为First Name 列增加ID:
<TableColumn fx:id="firstNameColumn" text="First Name">
2.指定排序顺序,在</items>和</TableView>两个标记之间增加代码:
</items>
<sortOrder>
<fx:reference source="firstNameColumn"/>
</sortOrder>
</TableView>
运行后界面如下:
定义列宽
下面为每一列增加prefWidth属性来增加列宽,如下所示:<TableColumn fx:id="firstnameColumn" text="First Name"<strong> prefWidth="100"</strong>>
<cellValueFactory><PropertyValueFactory property="firstName" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Last Name"<strong> prefWidth="100"></strong>
<cellValueFactory><PropertyValueFactory property="lastName" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Email Address" <strong>prefWidth="200"></strong>
<cellValueFactory><PropertyValueFactory property="email" />
</cellValueFactory>
</TableColumn>
运行效果如下图所示,列宽被扩大后所有数据得以全部显示。
设置表格单元的对齐方式
单元格中的数据对齐方式是可以定制的。你需要创建一个名为FormattedTableCellFactory的类来实现对应的逻辑,然后在FXML的<TableColumn>标签中设置对齐方式。
1. 在IDE中创建新类FormattedTableCellFactoryand
2.修改FormattedTableCellFactoryand类的代码,使其实现Callback接口,并在其中创建TextAlignment和Formt类实例。在下面的代码中,参数S是TableView泛型的类型、参数T是单元格的内容的类型:public class FormattedTableCellFactory<S, T>
implements Callback<TableColumn<S, T>, TableCell<S, T>> {
private TextAlignment alignment;
private Format format;
public TextAlignment getAlignment() {
return alignment;
}
public void setAlignment(TextAlignment alignment) {
this.alignment = alignment;
}
public Format getFormat() {
return format;
}
public void setFormat(Format format) {
this.format = format;
}
3.实现TabCell和TableColumn接口,将下列代码添加到类中。这段代码实现了TableCell接口的updateItem方法,并在其中调用了单元格setTextAlign方法。
@Override
@SuppressWarnings("unchecked")
public TableCell<S, T> call(TableColumn<S, T> p) {
TableCell<S, T> cell = new TableCell<S, T>() {
@Override
public void updateItem(Object item, boolean empty) {
if (item == getItem()) {
return;
}
super.updateItem((T) item, empty);
if (item == null) {
super.setText(null);
super.setGraphic(null);
} else if (format != null) {
super.setText(format.format(item));
} else if (item instanceof Node) {
super.setText(null);
super.setGraphic((Node) item);
} else {
super.setText(item.toString());
super.setGraphic(null);
}
}
};
cell.setTextAlignment(alignment);
switch (alignment) {
case CENTER:
cell.setAlignment(Pos.CENTER);
break;
case RIGHT:
cell.setAlignment(Pos.CENTER_RIGHT);
break;
default:
cell.setAlignment(Pos.CENTER_LEFT);
break;
}
return cell;
}
}
4.增加必需的import语句。
5.在fxml_tableview.fxml中的<cellValueFactory>节点之下增加下列语句来将FirstName居中对齐:
<TableColumn fx:id="firstNameColumn" text="First Name" prefWidth="100">
<cellValueFactory><PropertyValueFactory property="firstName" />
</cellValueFactory>
<cellFactory>
<FormattedTableCellFactory alignment="center">
</FormattedTableCellFactory>
</cellFactory>
</TableColumn>
你可以在其它的列中通过left、right或者center来指定不同的对齐方式。
运行结果如下:
向表格增加行
通过在FXMLTableViewControllerclass类中增加代码逻辑,可以使得用户可以向表格中增加数据。
1.打开FXMLTableViewController.java文件
2.按照下面的代码修改FXMLTableViewController类:
public class FXMLTableViewController {
@FXML private TableView<Person> tableView;
@FXML private TextField firstNameField;
@FXML private TextField lastNameField;
@FXML private TextField emailField;
@FXML
protected void addPerson(ActionEvent event) {
ObservableList<Person> data = tableView.getItems();
data.add(new Person(firstNameField.getText(),
lastNameField.getText(),
emailField.getText()
));
firstNameField.setText("");
lastNameField.setText("");
emailField.setText("");
}
}
3.根据下列代码修订import元素:
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
4. 在fxml_tableview.fxml文件中,在 </GridPane>前增加下面的代码:
</TableView> <HBox spacing="10" alignment="bottom_right" GridPane.columnIndex="0" GridPane.rowIndex="2"> <TextField fx:id="firstNameField" promptText="First Name" prefWidth="90"/> <TextField fx:id="lastNameField" promptText="Last Name" prefWidth="90"/> <TextField fx:id="emailField" promptText="email" prefWidth="150"/> <Button text="Add" onAction="#addPerson"/> </HBox> </GridPane>
运行后界面如下:
扩展学习
后续可以尝试一下这些内容:
1. 提供一个filter来校验输入的数据格式的正确性。
2. 使用CSS来自定义表格外观,区分区空行和非空行。可参考官方文档中的“Styling UIControls with CSS”。
3. 允许在表格中编辑数据。可参考官方文档中的“Editing Data in the Table”
看一看Introduction to FXML document,其中提供了更多关于FXML的信息。这篇文当在API文档的javafx.fxml包中。