2014-03-26 33 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; 
} 
相关问题