2014-03-26 34 views
0

首先,我必須道歉,因爲英語不是我的母語,但我會試着澄清我在問什麼。在ComboBox中更改ItemList,具體取決於另一個ComboBox選項

我在tableview中有一組行,每行每列都有不同的組合框。所以,組合框之間的交互必須是每行。如果在Combobox A1中,我選擇了項目1,在組合框A2中項目列表將被更新。 我的問題是,每個組合框A2,B2,C2等正在根據A1中的選擇進行更新...與B1,C1組合框相同。根據A1,我需要更新A2。 B2根據B1等

我設置組合框由cellfactory,因爲我必須從後面的數據保存在一個可序列化的對象。

希望很明確。

問候。

回答

1

這是非常痛苦......

TableCell,你可以觀察TableRow通過它的tableRowProperty()

TableRow中,您可以通過錶行的itemProperty()觀察該行中的項目。

當然,從該行中的項目,您可以觀察在您的模型類中定義的任何屬性,並相應地更新組合框中的項目列表。

痛苦的部分是,這些價值中的任何一個都可以,並且會在某些時候改變。因此,您需要觀察的事物不斷變化,並且您必須在發生這種情況時管理添加和刪除偵聽器。

Bindings.select方法應該可以幫助管理類似這樣的事情,但從JavaFX 8開始,每當遇到空值時都會向輸出打印巨大的堆棧跟蹤,並將其作爲頻繁使用的空值。所以我建議你做自己的聽衆管理,直到解決。 (出於某種原因,儘管在API文檔中明確支持在Bindings.select中定義的路徑中遇到null值,但JavaFX團隊似乎並沒有考慮到這一點。)

只是爲了讓它稍微更不愉快,TableCell<S,T>中的getTableRow()方法返回TableRow,而不是更明顯的TableRow<S>。 (這可能是我看不到的原因,但是,...)。所以你的代碼還會被拋出。

我創建了一個example,它的工作原理是:基於美國地理學的道歉,但我已經寫了很多示例。我真的希望我錯過了一些東西,並且有更簡單的方法來做到這一點:如果有人有更好的想法,請隨時提出建議。

最後一個注意:EasyBind庫可能提供了一種更簡單的方法來綁定到任意路徑的屬性。

0

由於@ James_D的例子不再運行,由於鏈接腐爛,我正在處理這個同樣的問題,這是我如何才能創造這種效果。

View the full test case here.

我延伸內建ComboBoxTableCell<S, T>以暴露必要的字段。自定義TableCell有一個Supplier<S> tableValue = (S) this.getTableRow().getItem();用於訪問適用的數據對象。此外,我反射性地檢索並存儲對單元格ComboBox的引用。因爲它在超類中被懶惰地實例化了,所以我也必須在反射之前通過反射來設置它。最後,我必須初始化ComboBox爲好,因爲這將是在javafx.scene.control.cell.CellUtils.createComboBox,因爲我手動創建。公開這些信息很重要,如下所示:

在列的CellFactory中,我們完成初始化ComboBoxCell。我們只需要創建一個我們自定義的ComboBoxTableCell的新實例,然後當第一次顯示組合框(例如,我們可以確定我們有一個與單元格關聯的數據對象)時,我們將ComboBox#itemsProperty綁定到Bindings.When,正確的ObservableList爲案件。

CellFactory:

column1.setCellFactory(c -> { 
     TransparentComboBoxTableCell<Data, Enum> tcbtc = new TransparentComboBoxTableCell<>(); 
     tcbtc.comboBox.setOnShown(e -> { 
      if (!tcbtc.comboBox.itemsProperty().isBound()) tcbtc.comboBox.itemsProperty().bind(
        Bindings.when(tcbtc.tableValue.get().base.isEqualTo(BASE.EVEN)).then(evens).otherwise(
        Bindings.when(tcbtc.tableValue.get().base.isEqualTo(BASE.ODD)).then(odds).otherwise(
        FXCollections.emptyObservableList() 
        )) 
      ); 
     }); 
     return tcbtc; 
    }); 

定製ComboBoxTableCell:

public static class TransparentComboBoxTableCell<S, T> extends ComboBoxTableCell<S, T> { 
    public TransparentComboBoxTableCell() { 
     this(FXCollections.observableArrayList()); 
    } 
    public TransparentComboBoxTableCell(ObservableList<T> startingItems) { 
     super(startingItems); 
     try { 
      Field f = ComboBoxTableCell.class.getDeclaredField("comboBox"); 
      f.setAccessible(true); 
      f.set(this, new ComboBox<>()); 
      comboBox = (ComboBox<T>) f.get(this); 
      // Setup out of javafx.scene.control.cell.CellUtils.createComboBox 
      // comboBox.converterProperty().bind(converter); 
      comboBox.setMaxWidth(Double.MAX_VALUE); 
      comboBox.getSelectionModel().selectedItemProperty().addListener((ov, oldValue, newValue) -> { 
       if (this.isEditing()) { 
        this.commitEdit((T) newValue); 
       } 
      }); 
     } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) { 
      Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex); 
      throw new Error("Error extracting 'comboBox' from ComboBoxTableCell", ex); 
     } 
     tableValue =() -> (S) this.getTableRow().getItem(); 
    } 

    public final ComboBox<T> comboBox; 
    public final Supplier<S> tableValue; 
} 
相關問題