声明:如需转载,请注明出处:http://blog.csdn.net/originer
原文地址:http://docs.oracle.com/javase/8/javafx/fxml-tutorial/fxml_tutorial_intermediate.htm在本章中,你将会创建一个地址簿应用程序,其中包括一个带有姓名和邮件地址的表格。本教程展示了如何操作带有数据的表格,包括数据排序,单元格中的数据对齐,向表格内增加行。
在开始之前,我们假定你对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文档可获取更多信息。
下图展现了运行效果:
定义数据模型
在JavaFX中使用Table的最佳实践之一是定义一个数据模型类来提供操作表格的方法和属性。下面创建一个Person类来定义地址簿的数据,类代码如下:
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包中。