JavaFX UI控件教程(十三)之Table View
翻译自 Table View
在本章中,您将学习如何使用JavaFX应用程序中的表执行基本操作,例如添加表,使用数据填充表以及编辑表行。
JavaFX SDK API中的几个类旨在以表格形式表示数据。用于创建JavaFX应用程序表中的最重要的类是TableView
,TableColumn
和TableCell
。您可以通过实现数据模型和应用单元工厂来填充表。
表类提供了内置功能,可以对列中的数据进行排序,并在必要时调整列的大小。
图12-1显示了表示通讯簿中的联系信息的典型表。
创建表
例12-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);}@Overridepublic 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);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
类来创建表控件。在示例12-1中,它被添加到VBox
布局容器中,但是,您可以将其直接添加到应用程序场景中。
示例12-1定义了三列,用于将以下信息存储在地址簿中:联系人的名字和姓氏以及电子邮件地址。列是使用TableColumn
类创建的。
该类的getColumns
方法TableView
将以前创建的列添加到表中。在应用程序中,您可以使用此方法动态添加和删除列。
您可以通过调用setVisible
方法来管理列的可见性。例如,如果应用程序的逻辑需要隐藏用户电子邮件地址,则可以按如下方式实现此任务:emailCol.setVisible(false)
。
例如,假设地址簿中的联系人有两个电子邮件帐户。然后,您需要两列来显示主电子邮件地址和辅助电子邮件地址。创建两个子列,然后调用该getColumns
方法,emailCol
如例12-2所示。
TableColumn firstEmailCol = new TableColumn("Primary");
TableColumn secondEmailCol = new TableColumn("Secondary");emailCol.getColumns().addAll(firstEmailCol, secondEmailCol);
将这些行添加到示例12-1并编译并运行应用程序代码后,该表将如图12-3所示。
虽然该表已添加到应用程序中,但会显示标准标题“表中没有内容”,因为未定义任何数据。您可以使用该setPlaceholder
方法指定Node
要在空表中显示的对象,而不是显示此标题。
定义数据模型
在JavaFX应用程序中创建表时,最佳实践是实现定义数据模型的类,并提供方法和字段以进一步使用表。例12-3创建了一个Person
类来定义地址簿中的数据。
public static 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
串属性的设置是为了使一个特定的数据元素的引用。
另外,为每个数据元素提供get
和set
方法。因此,例如,该getFirstName
方法返回firstName
属性的值,并且该setFirstName
方法指定此属性的值。
在Person
类中概述数据模型时,您可以创建一个ObservableList
数组并定义您希望在表中显示的数据行数。例12-4中的代码片段实现了此任务。
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")
);
下一步是将数据与表列相关联。您可以通过为每个数据元素定义的属性执行此操作,如例12-5所示。
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName")
);
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("lastName")
);
emailCol.setCellValueFactory(new PropertyValueFactory<Person,String>("email")
);
定义数据模型,并添加数据并与列关联时,可以使用类的setItems
方法将数据添加到表中TableView
:table.setItems(data)
。
由于该ObservableList
对象可以跟踪对其元素的任何更改,因此TableView
只要数据发生更改,内容就会自动更新。
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);}@Overridepublic 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 = new TableColumn("First Name");firstNameCol.setMinWidth(100);firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));TableColumn lastNameCol = new TableColumn("Last Name");lastNameCol.setMinWidth(100);lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));TableColumn emailCol = new TableColumn("Email");emailCol.setMinWidth(200);emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));table.setItems(data);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();}public static 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);}}
}
添加新行
图12-4中的表包含五行数据,到目前为止无法修改。
您可以使用文本字段在“名字”,“姓氏”和“电子邮件”列中输入新值。“ 文本字段”控件使您的应用程序可以接收来自用户的文本输入。例12-7创建了三个文本字段,定义了每个字段的提示文本,并创建了Add按钮。
final TextField addFirstName = new TextField();
addFirstName.setPromptText("First Name");
addFirstName.setMaxWidth(firstNameCol.getPrefWidth());
final TextField addLastName = new TextField();
addLastName.setMaxWidth(lastNameCol.getPrefWidth());
addLastName.setPromptText("Last Name");
final TextField addEmail = new TextField();
addEmail.setMaxWidth(emailCol.getPrefWidth());
addEmail.setPromptText("Email");final Button addButton = new Button("Add");
addButton.setOnAction(new EventHandler<ActionEvent>() {@Override public void handle(ActionEvent e) {data.add(new Person(addFirstName.getText(),addLastName.getText(),addEmail.getText()));addFirstName.clear();addLastName.clear();addEmail.clear();}
});
当用户单击“添加”按钮时,在文本字段中输入的值将包含在Person
构造函数中并添加到data
可观察列表中。因此,带有联系信息的新条目将显示在表格中。
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
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.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;public class FileChooserSample 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"));final HBox hb = new HBox();public static void main(String[] args) {launch(args);}@Overridepublic void start(Stage stage) {Scene scene = new Scene(new Group());stage.setTitle("Table View Sample");stage.setWidth(450);stage.setHeight(550);final Label label = new Label("Address Book");label.setFont(new Font("Arial", 20));table.setEditable(true);TableColumn firstNameCol = new TableColumn("First Name");firstNameCol.setMinWidth(100);firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));TableColumn lastNameCol = new TableColumn("Last Name");lastNameCol.setMinWidth(100);lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));TableColumn emailCol = new TableColumn("Email");emailCol.setMinWidth(200);emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));table.setItems(data);table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);final TextField addFirstName = new TextField();addFirstName.setPromptText("First Name");addFirstName.setMaxWidth(firstNameCol.getPrefWidth());final TextField addLastName = new TextField();addLastName.setMaxWidth(lastNameCol.getPrefWidth());addLastName.setPromptText("Last Name");final TextField addEmail = new TextField();addEmail.setMaxWidth(emailCol.getPrefWidth());addEmail.setPromptText("Email");final Button addButton = new Button("Add");addButton.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent e) {data.add(new Person(addFirstName.getText(),addLastName.getText(),addEmail.getText()));addFirstName.clear();addLastName.clear();addEmail.clear();}});hb.getChildren().addAll(addFirstName, addLastName, addEmail, addButton);hb.setSpacing(3);final VBox vbox = new VBox();vbox.setSpacing(5);vbox.setPadding(new Insets(10, 0, 0, 10));vbox.getChildren().addAll(label, table, hb);((Group) scene.getRoot()).getChildren().addAll(vbox);stage.setScene(scene);stage.show();}public static 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);}}
}
此应用程序不提供任何过滤器来检查,例如,是否以错误的格式输入了电子邮件地址。您可以在开发自己的应用程序时提供此类功能。
当前实现也不检查以确定是否输入空值。如果未提供任何值,则单击“添加”按钮会在表中插入一个空行。
图12-6显示了单击“添加”按钮后的表格。Emma White的联系方式现已显示在表格中。
按列排序数据
该TableView
级提供了内置的功能来在列中的数据进行排序。用户可以通过单击列标题来更改数据的顺序。第一次单击启用升序排序,第二次单击启用降序排序,第三次单击禁用排序。默认情况下,不应用排序。
用户可以对表中的多个列进行排序,并在排序操作中指定每个列的优先级。要对多个列进行排序,用户在单击要排序的每个列的标题时按Shift键。
在图12-7中,升序排序顺序应用于名字,而姓氏则按降序排序。请注意,第一列优先于第二列。
您还可以通过TableColumn
在TableView.sortOrder
可观察列表中添加和删除实例来指定要排序的列。此列表中的列顺序表示排序优先级(例如,零项的优先级高于第一项)。
要禁止对数据进行排序,请setSortable(false)
在列上调用该方法。
编辑表格中的数据
将TableView
不仅呈现类的表格数据,但它也提供了一些功能来编辑它。使用此setEditable
方法可以编辑表格内容。
使用该setCellFactory
方法在TextFieldTableCell
类的帮助下将表格单元格重新实现为文本字段。该setOnEditCommit
方法处理编辑并将更新的值分配给相应的表格单元格。示例12-9显示了如何应用这些方法来处理名字,姓氏和电子邮件列中的单元格编辑。
firstNameCol.setCellFactory(TextFieldTableCell.forTableColumn());
firstNameCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, String>>() {@Overridepublic void handle(CellEditEvent<Person, String> t) {((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).setFirstName(t.getNewValue());}}
);lastNameCol.setCellFactory(TextFieldTableCell.forTableColumn());
lastNameCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, String>>() {@Overridepublic void handle(CellEditEvent<Person, String> t) {((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).setLastName(t.getNewValue());}}
);emailCol.setCellFactory(TextFieldTableCell.forTableColumn());
emailCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, String>>() {@Overridepublic void handle(CellEditEvent<Person, String> t) {((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).setEmail(t.getNewValue());}}
);
示例12-10具有启用单元格编辑的TableViewSample
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.HBox;
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"));final HBox hb = new HBox();public static void main(String[] args) {launch(args);}@Overridepublic void start(Stage stage) {Scene scene = new Scene(new Group());stage.setTitle("Table View Sample");stage.setWidth(450);stage.setHeight(550);final Label label = new Label("Address Book");label.setFont(new Font("Arial", 20));table.setEditable(true);TableColumn firstNameCol = new TableColumn("First Name");firstNameCol.setMinWidth(100);firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));firstNameCol.setCellFactory(TextFieldTableCell.forTableColumn());firstNameCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, String>>() {@Overridepublic void handle(CellEditEvent<Person, String> t) {((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).setFirstName(t.getNewValue());}});TableColumn lastNameCol = new TableColumn("Last Name");lastNameCol.setMinWidth(100);lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));lastNameCol.setCellFactory(TextFieldTableCell.forTableColumn());lastNameCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, String>>() {@Overridepublic void handle(CellEditEvent<Person, String> t) {((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).setLastName(t.getNewValue());}});TableColumn emailCol = new TableColumn("Email");emailCol.setMinWidth(200);emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));emailCol.setCellFactory(TextFieldTableCell.forTableColumn());emailCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, String>>() {@Overridepublic void handle(CellEditEvent<Person, String> t) {((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).setEmail(t.getNewValue());}});table.setItems(data);table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);final TextField addFirstName = new TextField();addFirstName.setPromptText("First Name");addFirstName.setMaxWidth(firstNameCol.getPrefWidth());final TextField addLastName = new TextField();addLastName.setMaxWidth(lastNameCol.getPrefWidth());addLastName.setPromptText("Last Name");final TextField addEmail = new TextField();addEmail.setMaxWidth(emailCol.getPrefWidth());addEmail.setPromptText("Email");final Button addButton = new Button("Add");addButton.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent e) {data.add(new Person(addFirstName.getText(),addLastName.getText(),addEmail.getText()));addFirstName.clear();addLastName.clear();addEmail.clear();}});hb.getChildren().addAll(addFirstName, addLastName, addEmail, addButton);hb.setSpacing(3);final VBox vbox = new VBox();vbox.setSpacing(5);vbox.setPadding(new Insets(10, 0, 0, 10));vbox.getChildren().addAll(label, table, hb);((Group) scene.getRoot()).getChildren().addAll(vbox);stage.setScene(scene);stage.show();}public static 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);}}
}
请注意,TextField
控件的默认实现要求用户按Enter键提交编辑。您可以重新定义TextField
行为以在焦点更改上提交编辑,这是预期的用户体验。尝试修改代码来实现这样的替代行为。
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;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"));final HBox hb = new HBox();public static void main(String[] args) {launch(args);}@Overridepublic void start(Stage stage) {Scene scene = new Scene(new Group());stage.setTitle("Table View Sample");stage.setWidth(450);stage.setHeight(550);final Label label = new Label("Address Book");label.setFont(new Font("Arial", 20));table.setEditable(true);Callback<TableColumn, TableCell> cellFactory =new Callback<TableColumn, TableCell>() {public TableCell call(TableColumn p) {return new EditingCell();}};TableColumn firstNameCol = new TableColumn("First Name");firstNameCol.setMinWidth(100);firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));firstNameCol.setCellFactory(cellFactory);firstNameCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, String>>() {@Overridepublic void handle(CellEditEvent<Person, String> t) {((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).setFirstName(t.getNewValue());}});TableColumn lastNameCol = new TableColumn("Last Name");lastNameCol.setMinWidth(100);lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));lastNameCol.setCellFactory(cellFactory);lastNameCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, String>>() {@Overridepublic void handle(CellEditEvent<Person, String> t) {((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).setLastName(t.getNewValue());}});TableColumn emailCol = new TableColumn("Email");emailCol.setMinWidth(200);emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));emailCol.setCellFactory(cellFactory);emailCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, String>>() {@Overridepublic void handle(CellEditEvent<Person, String> t) {((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).setEmail(t.getNewValue());}});table.setItems(data);table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);final TextField addFirstName = new TextField();addFirstName.setPromptText("First Name");addFirstName.setMaxWidth(firstNameCol.getPrefWidth());final TextField addLastName = new TextField();addLastName.setMaxWidth(lastNameCol.getPrefWidth());addLastName.setPromptText("Last Name");final TextField addEmail = new TextField();addEmail.setMaxWidth(emailCol.getPrefWidth());addEmail.setPromptText("Email");final Button addButton = new Button("Add");addButton.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent e) {data.add(new Person(addFirstName.getText(),addLastName.getText(),addEmail.getText()));addFirstName.clear();addLastName.clear();addEmail.clear();}});hb.getChildren().addAll(addFirstName, addLastName, addEmail, addButton);hb.setSpacing(3);final VBox vbox = new VBox();vbox.setSpacing(5);vbox.setPadding(new Insets(10, 0, 0, 10));vbox.getChildren().addAll(label, table, hb);((Group) scene.getRoot()).getChildren().addAll(vbox);stage.setScene(scene);stage.show();}public static 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);}}class EditingCell extends TableCell<Person, String> {private TextField textField;public EditingCell() {}@Overridepublic void startEdit() {if (!isEmpty()) {super.startEdit();createTextField();setText(null);setGraphic(textField);textField.selectAll();}}@Overridepublic void cancelEdit() {super.cancelEdit();setText((String) getItem());setGraphic(null);}@Overridepublic void updateItem(String item, boolean empty) {super.updateItem(item, empty);if (empty) {setText(null);setGraphic(null);} else {if (isEditing()) {if (textField != null) {textField.setText(getString());}setText(null);setGraphic(textField);} else {setText(getString());setGraphic(null);}}}private void createTextField() {textField = new TextField(getString());textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()* 2);textField.focusedProperty().addListener(new ChangeListener<Boolean>(){@Overridepublic void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) {if (!arg2) {commitEdit(textField.getText());}}});}private String getString() {return getItem() == null ? "" : getItem().toString();}}
}
请注意,随着TextFieldTableCell
实现的发展,这种方法在将来的版本中可能会变得多余,以提供更好的用户体验。
将数据映射添加到表中
启动JavaFX SDK 2.2,您可以将Map
数据添加到表中。使用示例12-12中MapValueFactory
所示的类来显示表中学生ID的映射。
import java.util.HashMap;
import java.util.Map;
import javafx.application.Application;
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.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.MapValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;public class TableViewSample extends Application {public static final String Column1MapKey = "A";public static final String Column2MapKey = "B";public static void main(String[] args) {launch(args);}@Overridepublic 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("Student IDs");label.setFont(new Font("Arial", 20));TableColumn<Map, String> firstDataColumn = new TableColumn<>("Class A");TableColumn<Map, String> secondDataColumn = new TableColumn<>("Class B");firstDataColumn.setCellValueFactory(new MapValueFactory(Column1MapKey));firstDataColumn.setMinWidth(130);secondDataColumn.setCellValueFactory(new MapValueFactory(Column2MapKey));secondDataColumn.setMinWidth(130);TableView table_view = new TableView<>(generateDataInMap());table_view.setEditable(true);table_view.getSelectionModel().setCellSelectionEnabled(true);table_view.getColumns().setAll(firstDataColumn, secondDataColumn);Callback<TableColumn<Map, String>, TableCell<Map, String>>cellFactoryForMap = new Callback<TableColumn<Map, String>,TableCell<Map, String>>() {@Overridepublic TableCell call(TableColumn p) {return new TextFieldTableCell(new StringConverter() {@Overridepublic String toString(Object t) {return t.toString();}@Overridepublic Object fromString(String string) {return string;} });}};firstDataColumn.setCellFactory(cellFactoryForMap);secondDataColumn.setCellFactory(cellFactoryForMap);final VBox vbox = new VBox();vbox.setSpacing(5);vbox.setPadding(new Insets(10, 0, 0, 10));vbox.getChildren().addAll(label, table_view);((Group) scene.getRoot()).getChildren().addAll(vbox);stage.setScene(scene);stage.show();}private ObservableList<Map> generateDataInMap() {int max = 10;ObservableList<Map> allData = FXCollections.observableArrayList();for (int i = 1; i < max; i++) {Map<String, String> dataRow = new HashMap<>();String value1 = "A" + i;String value2 = "B" + i;dataRow.put(Column1MapKey, value1);dataRow.put(Column2MapKey, value2);allData.add(dataRow);}return allData;}
}
TableView
TableColumn
TableCell
TextField
TextFieldTableCell
MapValueFactory
Button
JavaFX UI控件教程(十三)之Table View相关推荐
- JavaFX UI控件教程(二)之JavaFX UI控件
翻译自 JavaFX UI控件 本章概述了通过API提供的JavaFX UI控件. JavaFX UI控件是使用场景图中的节点构建的.因此,控件可以使用JavaFX平台的视觉丰富功能.由于JavaF ...
- JavaFX UI控件教程(一)之简述
翻译自 JavaFX UI控件概述 关于本教程 本教程介绍JavaFX API中提供的内置JavaFX UI控件. 该文件包含以下章节: JavaFX UI控件 标签 按钮 单选按钮 切换按钮 复选 ...
- JavaFX UI控件教程(八)之Choice Box
翻译自 Choice Box 本章介绍了选项框,这些UI控件提供了在几个选项之间快速选择的支持. 使用ChoiceBox该类将选择框添加到JavaFX应用程序.其简单的实现如图7-1所示. 图7- ...
- JavaFX UI控件教程(二十三)之Menu
翻译自 Menu 本章介绍如何创建菜单和菜单栏,添加菜单项,将菜单分组,创建子菜单以及设置上下文菜单. 您可以使用以下JavaFX API类在JavaFX应用程序中构建菜单. 菜单栏 菜单项 菜单 ...
- JavaFX UI控件教程(二十八)之UI控件的自定义
翻译自 Customization of UI Controls 本章介绍了UI控件自定义的各个方面,并总结了Oracle提供的一些提示和技巧,以帮助您修改UI控件的外观和行为. 您可以通过应用层叠 ...
- JavaFX UI控件教程(二十二)之Titled Pane和Accordion
翻译自 Titled Pane and Accordion 本章介绍如何在JavaFX应用程序中使用accordion和title窗格的组合. 标题窗格是带标题的面板.它可以打开和关闭,它可以封装任 ...
- JavaFX UI控件教程(二十一)之Tooltip
翻译自 Tooltip 在本章中,您将了解工具提示,即当鼠标光标悬停该控件时,可以为任何UI控件设置的控件. 的Tooltip类表示通常用于显示关于所述用户接口的控制附加信息的公共UI组件.可以通过 ...
- JavaFX UI控件教程(二十)之HTML Editor
翻译自 HTML Editor 在本章中,您将学习如何使用嵌入式HTML编辑器编辑JavaFX应用程序中的文本. 该HTMLEditor控件是一个功能齐全的富文本编辑器.它的实现基于HTML5的文档 ...
- JavaFX UI控件教程(十八)之Progress Bar和Progress Indicator
翻译自 Progress Bar and Progress Indicator 在本章中,您将了解进度指示器和进度条,以及可视化JavaFX应用程序中任何操作进度的UI控件. 本ProgressIn ...
- JavaFX UI控件教程(十六)之Separator
翻译自 Separator 本章介绍如何使用分隔符组织JavaFX应用程序的UI组件. SeparatorJavaFX API中可用的类表示水平或垂直分隔线.它用于划分应用程序用户界面的元素,不会产 ...
最新文章
- 偏差是什么?一文读懂偏差
- python isalpha()
- 无线覆盖项目地勘——无线地勘记录
- java.lang.NoClassDefFoundError comfasterxmljacksonannotationJsonView
- MasterPage + UpdatePanel + FileUpload
- labelimg如何调整框的颜色_P图改字:来看看吧!教你如何用PS墙壁发光灯泡广告文字图片...
- 图神经网络(一)图信号处理与图卷积神经网络(2)图信号与图的拉普拉斯矩阵
- 用BusyBox制作Linux根文件系统
- mysql注入漏洞语句,web安全之sql注入漏洞
- java中session的作用_java中session的工作原理是什么?和Cookies有何区别?
- python每隔30s检查一次_Python的全局解释器锁
- 【英语学习】【WOTD】apposite 释义/词源/示例
- Android状态选择器用法总结
- java jax ws_Java 7是否包含JAX-WS实现或API?
- Axure RP安装破解汉化以及发布到至AxureShare
- Ubuntu 安装绿联CM448无线网卡驱动
- 单片机74LS164C语言例子,74ls164单片机编程汇总(跑马灯/驱动数码管)
- kd树的构造和搜索(超详细)
- 怎么设计计算机网络共享,怎么设置网络共享?教大家两种设置共享网络的方法...
- 南京梧桐树美吗?生活在梧桐树下的痛苦,春天掉毛、夏天掉皮、秋天掉叶,一年三掉,砸的你是一把鼻涕一把泪。
热门文章
- java并发之synchronized实现原理及其优化
- [Java基础]反射概述
- php 如何生成二级目录json,使用PHP根据已解码的JSON创建文件夹/文件结构
- css3是什么 ptml_CSS3
- mysql数据剪切到新表_6、MySQL核心DDL语句
- Java Socket编程详解
- 2019 ICPC Asia Nanchang Regional K.Tree 树上启发式合并 + 动态开点线段树
- CF1479B Painting the Array
- P4878 [USACO05DEC]Layout G
- 线性代数五之高斯消元——[SDOI2010]外星千足虫,[HNOI2013]游走,[HNOI2011]XOR和路径,[hdu 4035]Maze