2016-08-12 72 views
1

我處於以下情況。我從模型類Foo有數據填充一個TableViewJavaFX - TableView - 該字段的字段和字段的更改

public class Foo { 
    private StringProperty someText; 
    private Bar someObject; 

    // getters, setters and properties dropped for clarity 
} 

此類具有類型Bar的領域:

public class Bar { 
    private StringProperty someText; 

    // getters, setters and properties dropped for clarity 
} 

其中一列必須顯示從Bar的someText文。所以我將該StringProperty綁定到列。

但是,當Foo中的整個Bar對象被另一個替換時,該表也應該更新。所以我在Foo中創建了一個包含Bar的ObjectProperty,並將該屬性綁定到該列。當然,現在它不再聽任何改變Bar的someText。

如何獲得這些解決方案的「組合」,以便表可以偵聽對象本身及其字段的變化?

回答

2

只需使用JavaFX的API,你可以做

TableColumn<Foo, String> barColumn = new TableColumn<>("Bar"); 

barColumn.setCellValueFactory(cellData -> 
    Bindings.selectString(cellData.getValue().barProperty(), "someText")); 

我真的不喜歡的一對夫婦的原因API的一部分。首先,沒有編譯時檢查:您只需將該屬性的名稱作爲字符串提供,因此如果您有錯字,它只會在運行時顯示。其次,如果foo.getBar()返回null(它將在表格單元格中),則會生成一堆警報到stderr。這些只是令人討厭的(它們不會阻止任何運行),並且實際上不應該存在,因爲根據API文檔,這是受支持的用例。但是,它會起作用。


對於一個更強大和更少的傳統風格的實現,你可以用托馬斯Mikula的ReactFX library,2.0或更高版本,其中包括像這樣綁定的支持。使用該庫你會做

barColumns.setCellValueFactory(cellData -> 
    Val.flatMap(cellData.getValue().barProperty(), Bar::someTextProperty)); 

這有編譯時檢查和類型檢查等,並沒有虛假的警告。

2

您可以使用Bindings.select通過多級層次結構選擇值。這使您可以創建一個單一cellValueFactory類:

import java.util.Arrays; 
import javafx.beans.NamedArg; 
import javafx.beans.binding.Bindings; 
import javafx.beans.value.ObservableValue; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.util.Callback; 

public class NestedPropertyValueFactory<S, T> implements Callback<TableColumn.CellDataFeatures<S, T>, ObservableValue<T>> { 

    private final String[] steps; 
    private final PropertyValueFactory firstStepSelector; 

    public NestedPropertyValueFactory(String... properties) { 
     firstStepSelector = new PropertyValueFactory<>(properties[0]); 
     this.steps = Arrays.copyOfRange(properties, 1, properties.length); 
    } 

    /** 
    * @param property a string containing the names of the properties seperated 
    * by '.'. (For easy use from fxml file) 
    */ 
    public NestedPropertyValueFactory(@NamedArg("property") String property) { 
     this(property.split("\\.")); 
    } 

    @Override 
    public ObservableValue<T> call(TableColumn.CellDataFeatures<S, T> param) { 
     // use PropertyValueFactory for first step and Bindings.select for 
     // additonal steps. 
     return Bindings.select(firstStepSelector.call(param), steps); 
    } 

} 

請注意,如果任何中間步驟產生null,你會得到System.err警告。

同樣對於這個類,您需要使用符合命名約定的屬性方法,即在這種情況下方法的名稱應該是someObjectPropertysomeTextProperty。這使您可以使用類似PropertyValueFactory類:

column.setCellValueFactory(new NestedPropertyValueFactory<>("someObject", "someText")); 

column.setCellValueFactory(new NestedPropertyValueFactory<>("someObject.someText")); 
相關問題