自定义 TableView 列的可观察性:如何访问类的所有属性?
2024-03-05 04:31:00
## 自定义 TableView 列的可观察性:超越 PropertyValueFactory
作为程序员,在设计复杂的 GUI 界面时,我们经常需要处理表格数据。TableView 控件是 JavaFX 中用于呈现表格数据的强大组件。但是,默认情况下,TableView 列仅绑定到特定对象的属性,这可能会限制我们访问其他相关数据的灵活性。本文将深入探讨一种有效的方法,利用 ObservableValueFactory 和自定义单元格工厂,使自定义 TableView 列可观察,从而可以访问类的所有属性,而不仅仅是绑定的属性显示值。
为什么需要可观察性?
在某些情况下,我们可能需要在 TableView 单元格的更新方法中使用类的所有属性,而不仅仅是绑定的属性显示值。这对于创建复杂的展示或交互式表格至关重要。例如,我们可能有一个包含多个属性的对象,我们希望在单元格中显示它们的组合值。
使用 ObservableValueFactory
为了使自定义 TableView 列可观察,我们可以在创建列时使用 ObservableValueFactory。ObservableValueFactory 提供了一个 ObservableValue 接口的实现,该接口返回列中单元格表示的对象。通过使用 ObservableValueFactory,我们不必使用 PropertyValueFactory,从而可以访问对象的任何属性。
col_2.setCellValueFactory(data -> new ObservableValue<>()
{
@Override
public void addListener(ChangeListener<? super myclass> listener) {}
@Override
public void removeListener(ChangeListener<? super myclass> listener) {}
@Override
public myclass getValue()
{
return data.getValue();
}
@Override
public void addListener(InvalidationListener listener) {}
@Override
public void removeListener(InvalidationListener listener) {
}
});
创建自定义单元格工厂
使用 ObservableValueFactory 后,我们需要创建自定义单元格工厂,以便在列中实现可观察性。单元格工厂负责创建和更新表格单元格的图形表示。
col_2.setCellFactory(p ->
{
TableCell<myclass,myclass> cell = new TableCell<>()
{
@Override
protected void updateItem(myclass item, boolean empty)
{
if (item != null)
{
Label l = new Label();
l.setText("combination display " + item.fld2Property().getValue() + " " + item.fld4Property().getValue());
setGraphic(l);
}
else
{
setGraphic(null);
setText(null);
}
}
};
return cell;
});
在自定义单元格工厂中,我们创建一个 TableCell 实例,并覆盖其 updateItem 方法。在 updateItem 方法中,我们可以访问通过 ObservableValueFactory 提供的对象,并使用其属性创建单元格的图形表示。
示例代码
以下示例代码演示了如何使用 ObservableValueFactory 和自定义单元格工厂使自定义 TableView 列可观察:
// 创建自定义的 myclass 对象,其中包含多个属性
public class myclass
{
private IntegerProperty fld1;
private StringProperty fld2;
private StringProperty fld3;
private StringProperty fld4;
// 构造函数
public myclass(int fld1, String fld2, String fld3, String fld4)
{
this.fld1 = new SimpleIntegerProperty(fld1);
this.fld2 = new SimpleStringProperty(fld2);
this.fld3 = new SimpleStringProperty(fld3);
this.fld4 = new SimpleStringProperty(fld4);
}
// 省略 getter 和 setter 方法
}
// 在控制器类中
public class HelloController
{
// 定义 TableView 和列
@FXML
private TableView<myclass> tableView;
@FXML
private TableColumn<myclass, Integer> col_1;
@FXML
private TableColumn<myclass, myclass> col_2;
@FXML
private TableColumn<myclass, String> col_3;
@FXML
private TableColumn<myclass, String> col_4;
// 初始化数据
public void initialize()
{
// 创建 ObservableValueFactory
col_2.setCellValueFactory(data -> new ObservableValue<>()
{
@Override
public void addListener(ChangeListener<? super myclass> listener) {}
@Override
public void removeListener(ChangeListener<? super myclass> listener) {}
@Override
public myclass getValue()
{
return data.getValue();
}
@Override
public void addListener(InvalidationListener listener) {}
@Override
public void removeListener(InvalidationListener listener) {}
});
// 创建自定义单元格工厂
col_2.setCellFactory(p ->
{
TableCell<myclass, myclass> cell = new TableCell<>()
{
@Override
protected void updateItem(myclass item, boolean empty)
{
if (item != null)
{
Label l = new Label();
l.setText("combination display " + item.fld2Property().getValue() + " " + item.fld4Property().getValue());
setGraphic(l);
}
else
{
setGraphic(null);
setText(null);
}
}
};
return cell;
});
// 设置其他列
col_1.setCellValueFactory(new PropertyValueFactory<>("fld1"));
col_3.setCellValueFactory(new PropertyValueFactory<>("fld3"));
col_4.setCellValueFactory(new PropertyValueFactory<>("fld4"));
// 加载数据到 TableView
tableView.setItems(FXCollections.observableArrayList(origlist));
}
}
通过使用 ObservableValueFactory 和自定义单元格工厂,我们成功地使自定义 TableView 列可观察,从而能够在单元格的 updateItem 方法中访问类的所有属性,这增强了我们创建灵活且交互式表格的能力。
常见问题解答
1. 使用 ObservableValueFactory 和自定义单元格工厂有什么好处?
- 访问类的所有属性,而不受 PropertyValueFactory 的限制。
- 允许在单元格中创建复杂的显示,组合不同的属性值。
- 增强表格数据的灵活性,使其适用于更广泛的场景。
2. ObservableValueFactory 和 PropertyValueFactory 之间的区别是什么?
- ObservableValueFactory 返回一个 ObservableValue 对象,该对象提供列中单元格表示的对象。
- PropertyValueFactory 将特定对象的属性直接绑定到列。
3. 我可以在 JavaFX 中使用 ObservableValueFactory 来创建所有自定义列吗?
- 对于需要访问类的所有属性或创建自定义单元格显示的列,ObservableValueFactory 是理想的选择。对于简单列,使用 PropertyValueFactory 可能更合适。
4. 如何在使用 ObservableValueFactory 的情况下访问单元格中对象的属性?
- 在自定义单元格工厂的 updateItem 方法中,您可以通过调用 getValue() 方法访问 ObservableValue 中存储的对象。然后,您可以使用对象属性来创建单元格的图形表示。
5. 是否可以在其他类型的 JavaFX 组件中使用 ObservableValueFactory?
- ObservableValueFactory 可以用于需要显示和操作可观察对象的任何 JavaFX 组件。它不仅限于 TableView 列。