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>() {
@Override
protected 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);
@Override
public 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");
应用。