【发布时间】:2015-09-01 10:58:31
【问题描述】:
我有一个 TableView,它源自 java.util.Date 类型的遗留 Java Bean 中的一个属性。我希望将日期字符串的格式自定义为 HH:mm:ss
我正在寻找一个本机 JavaFX 实用程序,用于创建采用 java.util.DateFormat 或 javafx.util.StringConverter 的 ObservableValue 包装器
我发现 Bindings.format() 类可以用来包装 ObservableValue,但是这只允许 printf 格式模式,如 %04d 等,而不是任何自定义日期特定格式。
我想出的最好方法是将 Bindings.bindBidirectional(property, property, format) 与 CellFactory 返回的虚拟 StringProperty 一起使用。这可以简化吗?这会导致内存泄漏吗?
public class OldBeanTableView extends Application {
public class OldBean {
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public static final String PROPERTY_NAME_FOO = "foo";
private Date foo = new Date();
public Date getFoo() {
return foo;
}
public void setFoo(Date foo) {
Date oldValue = this.foo;
this.foo = foo;
pcs.firePropertyChange(PROPERTY_NAME_FOO, oldValue, foo);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
}
private class LegacyValueFactory<T, F> implements Callback<CellDataFeatures<T, String>, ObservableValue<String>> {
private String propertyName;
private Format format;
public LegacyValueFactory(String propertyName, Format format) {
this.propertyName = propertyName;
this.format = format;
}
@Override
public ObservableValue<String> call(CellDataFeatures<T, String> param) {
try {
Property<String> formattedString = new SimpleStringProperty();
Property<F> original = JavaBeanObjectPropertyBuilder.create().name(propertyName).bean(param.getValue()).build();
Bindings.bindBidirectional(formattedString, original, format);
return formattedString;
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
}
@Override
public void start(Stage primaryStage) throws Exception {
ObservableList<OldBean> beans = FXCollections.observableArrayList();
beans.add(new OldBean());
TableView<OldBean> tableView = new TableView<>();
TableColumn<OldBean, String> column = new TableColumn<OldBeanTableView.OldBean, String>();
tableView.getColumns().add(column);
column.setCellValueFactory(new LegacyValueFactory<OldBean, String>("foo", new SimpleDateFormat("HH:mm:ss")));
tableView.setItems(beans);
primaryStage.setScene(new Scene(tableView));
primaryStage.show();
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
() -> beans.get(0).setFoo(new Date(beans.get(0).getFoo().getTime() + 1000)), 0, 1, TimeUnit.SECONDS);
}
public static void main(String[] args) {
launch(args);
}
}
【问题讨论】:
-
在这种情况下,我通常会使用刚刚返回
JavaBeanObjectProperty<Date>的TableColumn<OldBean, Date>和cellValueFactory(即使用Date作为列的数据类型)。然后还定义一个cellFactory来执行格式化。这会起作用吗,还是出于某种原因您真的需要列中的数据类型为String? -
我只将其键入为字符串,因为 Bindings.bindBindirectory(a, b, c) 迫使我走这条路。我认为 cellFactory 自定义是为了布局问题,但你是对的,我可以将它用于字符串格式化......如果你想把它写成我会接受的答案。