1. 表格组件简介
TableView
:用于显示数据的二维表格,支持列排序、选择、编辑等功能。TreeTableView
:类似于TableView
,但支持分层数据展示,适合树形结构的数据。
2. TableView
的常用方法
2.1 构造方法
TableView()
:创建一个空的表格视图。TableView(ObservableList items)
:使用指定的初始数据创建表格。
2.2 列定义相关方法
TableColumn
:定义表格的一列,其中S
是表的模型类,T
是列的数据类型。
常见方法如下:
方法名 | 说明 | 示例 |
---|---|---|
setCellValueFactory() | 设置列的值工厂,用于指定列数据的来源。 | nameColumn.setCellValueFactory(new PropertyValueFactory<>("name")); |
setCellFactory() | 自定义单元格的渲染方式(如格式化日期)。 | priceColumn.setCellFactory(column -> new CurrencyCell()); |
setSortable(boolean value) | 设置列是否支持排序,默认值为 true 。 | nameColumn.setSortable(false); |
setPrefWidth(double value) | 设置列的首选宽度。 | priceColumn.setPrefWidth(150); |
2.3 表格数据操作方法
方法名 | 说明 | 示例 |
---|---|---|
setItems(ObservableList items) | 设置表格的数据集合。 | tableView.setItems(dataList); |
getItems() | 获取表格当前的数据集合。 | ObservableList items = tableView.getItems(); |
refresh() | 刷新表格以更新显示内容。 | tableView.refresh(); |
2.4 选择相关方法
方法名 | 说明 | 示例 |
---|---|---|
getSelectionModel() | 获取表格的选择模型,用于处理选中行的操作。 | tableView.getSelectionModel().getSelectedItem(); |
setSelectionMode() | 设置选择模式(单选或多选)。 | tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); |
3. 常见问题及解决方案
3.1 列数据绑定问题
问题: 数据类的字段未使用 JavaFX 属性(
Property
),导致表格数据无法自动更新。
解决方法: 使用 SimpleStringProperty
等属性包装字段,并在数据类中提供 getter 和 setter 方法。
public class Person {private final SimpleStringProperty name;private final SimpleIntegerProperty age;public Person(String name, int age) {this.name = new SimpleStringProperty(name);this.age = new SimpleIntegerProperty(age);}public String getName() {return name.get();}public void setName(String name) {this.name.set(name);}public int getAge() {return age.get();}public void setAge(int age) {this.age.set(age);}
}
3.2 表格刷新问题
问题: 更新数据后表格未自动刷新。
解决方法: 调用 refresh()
方法强制刷新表格。
tableView.refresh();
3.3 自定义单元格样式
问题: 默认样式不满足需求,例如高亮特定数据行。
解决方法: 使用 setCellFactory
自定义渲染逻辑。
statusColumn.setCellFactory(column -> new TableCell<Person, String>() {@Overrideprotected void updateItem(String item, boolean empty) {super.updateItem(item, empty);if (item != null && !empty) {setText(item);setStyle(item.equals("Active") ? "-fx-background-color: lightgreen;" : "-fx-background-color: lightcoral;");} else {setText(null);setStyle("");}}
});
4. 完整案例
以下是一个完整的 TableView
案例,展示如何定义表格、绑定数据、自定义单元格渲染,以及处理常见问题。
4.1 数据模型
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;public class Person {private final SimpleStringProperty name;private final SimpleIntegerProperty age;private final SimpleStringProperty status;public Person(String name, int age, String status) {this.name = new SimpleStringProperty(name);this.age = new SimpleIntegerProperty(age);this.status = new SimpleStringProperty(status);}public String getName() {return name.get();}public void setName(String name) {this.name.set(name);}public SimpleStringProperty nameProperty() {return name;}public int getAge() {return age.get();}public void setAge(int age) {this.age.set(age);}public SimpleIntegerProperty ageProperty() {return age;}public String getStatus() {return status.get();}public void setStatus(String status) {this.status.set(status);}public SimpleStringProperty statusProperty() {return status;}
}
4.2 主界面代码
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;import java.util.stream.Collectors;public class TableViewExample extends Application {private ObservableList<Person> masterData = FXCollections.observableArrayList(new Person("Alice", 30, "Active"),new Person("Bob", 25, "Inactive"),new Person("Charlie", 35, "Active"));private ObservableList<Person> filteredData = FXCollections.observableArrayList(masterData);@Overridepublic void start(Stage primaryStage) {// 创建 TableView 和列TableView<Person> tableView = new TableView<>();TableColumn<Person, String> nameColumn = new TableColumn<>("Name");nameColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty());TableColumn<Person, Integer> ageColumn = new TableColumn<>("Age");ageColumn.setCellValueFactory(cellData -> cellData.getValue().ageProperty().asObject());TableColumn<Person, String> statusColumn = new TableColumn<>("Status");statusColumn.setCellValueFactory(cellData -> cellData.getValue().statusProperty());tableView.getColumns().addAll(nameColumn, ageColumn, statusColumn);tableView.setItems(filteredData);// 搜索框TextField searchField = new TextField();searchField.setPromptText("Search...");searchField.textProperty().addListener((obs, oldText, newText) -> {filteredData.setAll(masterData.stream().filter(person -> person.getName().toLowerCase().contains(newText.toLowerCase())|| person.getStatus().toLowerCase().contains(newText.toLowerCase())).collect(Collectors.toList()));});// 添加按钮Button addButton = new Button("Add");addButton.setOnAction(e -> {masterData.add(new Person("New Person", 20, "Active"));filteredData.setAll(masterData);});// 删除按钮Button deleteButton = new Button("Delete");deleteButton.setOnAction(e -> {Person selectedPerson = tableView.getSelectionModel().getSelectedItem();if (selectedPerson != null) {masterData.remove(selectedPerson);filteredData.setAll(masterData);} else {showAlert(Alert.AlertType.WARNING, "No Selection", "Please select a row to delete.");}});// 修改按钮Button editButton = new Button("Edit");editButton.setOnAction(e -> {Person selectedPerson = tableView.getSelectionModel().getSelectedItem();if (selectedPerson != null) {// 弹出编辑窗口showEditDialog(primaryStage, selectedPerson);} else {showAlert(Alert.AlertType.WARNING, "No Selection", "Please select a row to edit.");}});// 布局HBox controls = new HBox(10, searchField, addButton, deleteButton, editButton);VBox root = new VBox(10, controls, tableView);Scene scene = new Scene(root, 600, 400);primaryStage.setTitle("JavaFX TableView Example");primaryStage.setScene(scene);primaryStage.show();}// 编辑对话框private void showEditDialog(Stage parentStage, Person selectedPerson) {// 新建一个编辑窗口Stage editDialog = new Stage();editDialog.initModality(Modality.WINDOW_MODAL);editDialog.initOwner(parentStage);editDialog.setTitle("Edit Person");// 创建输入框TextField nameField = new TextField(selectedPerson.getName());TextField statusField = new TextField(selectedPerson.getStatus());// 保存按钮Button saveButton = new Button("Save");saveButton.setOnAction(e -> {selectedPerson.setName(nameField.getText());selectedPerson.setStatus(statusField.getText());// 更新表格filteredData.setAll(masterData);editDialog.close();});// 布局VBox editLayout = new VBox(10, new Label("Name:"), nameField, new Label("Status:"), statusField, saveButton);Scene editScene = new Scene(editLayout, 300, 200);editDialog.setScene(editScene);editDialog.show();}// 显示警告框private void showAlert(Alert.AlertType alertType, String title, String message) {Alert alert = new Alert(alertType);alert.setTitle(title);alert.setHeaderText(null);alert.setContentText(message);alert.showAndWait();}public static void main(String[] args) {launch(args);}
}
5. 样式自定义
使用 JavaFX CSS
文件可以进一步定制表格的样式。
样式示例
.table-view .column-header-background {-fx-background-color: #2c3e50;
}.table-view .column-header .label {-fx-text-fill: white;
}.table-row-cell:odd {-fx-background-color: #f4f4f4;
}.table-row-cell:even {-fx-background-color: #ffffff;
}
在项目中添加 styles.css
并通过 scene.getStylesheets().add("styles.css");
应用。