在你舉的情況下,你應該使用單元格值工廠:
TableColumn<Person, String> columnExample = new TableColumn<>("Name");
columnExample.setCellValueFactory(cellData ->
new SimpleStringProperty(cellData.getValue().getPersonName()));
然後默認細胞工廠會做你想要什麼。
如果使用JavaFX property pattern實現模型,即你有
public class Person {
private final StringProperty personName = new SimpleStringProperty();
public StringProperty personNameProperty() {
return personName ;
}
public final String getPersonName() {
return personNameProperty().get();
}
public final void setPersonName(String name) {
personNameProperty().set(name);
}
}
那麼這將成爲
TableColumn<Person, String> columnExample = new TableColumn<>("Name");
columnExample.setCellValueFactory(cellData -> cellData.getValue().personNameProperty());
我經常使用的工具方法用於創建列,以減少代碼。基本的想法是編寫一個方法,將不同的事物參數化。在前面的兩個線路,即根據不同要創建的列的事情是:
- 文中的例子列(
"Name"
)和
- 從行項目去功能(
Person
實例)到包含要顯示的值的屬性。
第一個很容易:它只是一個String
。第二個有點棘手:您可以將其表示爲Function<Person, StringProperty>
,並將其定義爲lambda表達式p -> p.personNameProperty()
或方法參考Person::personNameProperty
。
這裏的問題當然是,並非每一列都將在Person
類型的TableView
中,並且並非每一列都將具有String
作爲其類型。所以我們也需要參數化這些。這可以通過定義具有兩個類型參數的通用方法來完成。我們用類型參數替代Person
,例如S
和String
通過第二類型參數(例如, T
。然後我們創建一個TableColumn<S,T>
,我們需要一個Function<S, Property<T>>
。因此,該方法是這樣的:
private <S,T> TableColumn<S,T> column(String text, Function<S, Property<T>> prop) {
TableColumn<S,T> col = new TableColumn<>(text);
col.setCellValueFactory(cellData -> prop.apply(cellData.getValue()));
return col ;
}
您可以
TableColumn<Person, String> columnExample = this.<Person, String>column("Name", Person::personNameProperty);
稱這在Java 8中,編譯器可以推斷泛型類型的方法(基本上,它看到Person::personNameProperty
是Function<Person, Property<String>>
的,因此它推斷S
是Person
和T
是String
),所以你可以這樣做:
TableColumn<Person, String> columnExample = column("Name", Person::personNameProperty);
我經常發現,在此設置我不需要除了將它傳遞給表中的列,因此代碼往往最終看起來像
table.getColumns().add(column("Name", Person::personNameProperty));
,如果你可以使用類似的技術真的確實需要一種生成細胞工廠的方法。在您的實例不同的事情是:
- 類型的行中的項目,並在細胞
- ,從該項目的小區(即從項目傳遞給獲得一個
String
功能該updateItem(...)
法)
因此,第一個是通過創建一個通用的方法,<S,T>
返回Callback<TableColumn<S,T>, TableCell<S,T>>
解決。二是通過使用Function<T, String>
類型的參數映射電池項目(類型T
)解決的String
:
public <S,T> Callback<TableColumn<S,T>, TableCell<S,T>>
cellFactory(Function<T, String> textExtractor) {
return col -> new TableCell<S,T>() {
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty) ;
if (empty || item == null) {
setText(null);
} else {
setText(textExtractor.apply(item));
}
}
};
}
,然後你原來的例子變得
columnExample.setCellFactory(cellFactory(Person::getPersonName));
最後,如果你需要的話,你可以結合所有這些想法。假設你有一個Address
類:
public class Address {
private String street ;
private String city ;
// etc etc
public String shortTextForm() {
return street+" ,"+city;
}
// ...
}
和Person
類:
public class Person {
private final StringProperty name = new SimpleStringProperty();
public StringProperty nameProperty() {
return name ;
}
public final String getName() {
return nameProperty().get();
}
public final void setName(String name) {
nameProperty().set(name);
}
private final ObjectProperty<Address> address = new SimpleObjectProperty<>();
public ObjectProperty<Address> addressProperty() {
return address ;
}
public Address getAddress() {
return addressProperty().get();
}
public void setAddress(Address address) {
addressProperty().set(address);
}
// other properties...
}
現在創建用於創建列的可重複使用的方法。這一次是要同時設置了cellValueFactory
(所以它需要一個Function<S,Property<T>>
)和cellFactory
(所以它需要一個Function<T, String>
):
private <S,T> TableColumn<S,T> column(String text, Function<S,Property<T>> prop,
Function<T,String> textExtractor) {
TableColumn<S,T> col = new TableColumn<>(text);
col.setCellValueFactory(cellData -> prop.apply(cellData.getValue()));
col.setCellFactory(c -> new TableCell<S,T>() {
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
} else {
setText(textExtractor.apply(item));
}
}
});
return col ;
}
,然後你只是做
TableView<Person> table = new TableView<>();
table.getColumns().add(column("Name", Person::nameProperty, s -> s));
table.getColumns().add(column("Address", Person::addressProperty, Address:shortTextForm));
爲什麼你在這種情況下使用細胞工廠,而不是細胞價值工廠? –
顯示什麼錯誤? –
好的,你的答案幫了我很大的忙,我得到的錯誤是一些問題,在我把桌子扔掉之後解決了。感謝你! – ImRaphael