这个问题进一步深入到了JavaFX: Disable multiple rows in TableView based on other TableView停止的地方。我想提出一个更一般性的话题,其他人也可以从中受益。
我还有两个桌面视图。当table2包含相同的对象时,我还希望禁用table1中的行。这是通过以下代码实现的:
//Check if a row needs to be disabled: this is achieved with a rowfactory
ObservableList<String> listOfSKUs = EasyBind.map(table1.getItems(),Product::getSKU);
table2.setRowFactory(tv -> {
TableRow<Product> row = new TableRow<>();
//The row doesnt need to be checked when it is empty, thats the first part
//The second part is a big OR: the row is a gift card OR the listOfSkus contains the row. In this last one, the amount also needs to be checked.
row.disableProperty().bind(Bindings.createBooleanBinding( () ->
row.getItem() != null &&
(row.getItem().getProductName().equals("Kadobon") ||
(listOfSKUs.contains(row.getItem().getSKU()) //&& some part to check for the amount)
), listOfSKUs, row.itemProperty() ));
return row;
});现在,我只希望在下列情况下禁用行:
我不知道如何检查金额,因为我需要与某些SKU相关的金额。如何在一个BooleanBinding中使用多个映射来创建这个映射?
任何帮助都是非常感谢的!
发布于 2014-10-29 15:15:10
在我看来,重新考虑对象模型可能会给您带来好处。您的Product似乎有两个不同的值,您称之为amount:一个在table1中显示,另一个在table2中显示。如果使用Product类的这两个不同字段,那么所有这些都变得容易得多,因为您可以用相同的实际对象(只是在列中显示不同的属性)来表示两个表中的项;然后禁用行的条件就变成了您正在查看的对象的一个函数(以及table2.getItems().contains(...))。
另一个选项可能是一个SKU类:
public class SKU {
private final StringProperty sku = ... ;
// Obviously use more meaningful names for these:
private final ObjectProperty<Product> table1Product = ... ;
private final ObjectProperty<Product> table2Product = ... ;
// getters, setters etc...
}然后,这两个表都可以是TableView<SKU>,其中的单元格值工厂位于列上,只需查看来自正确产品的属性。这样,表1的行工厂中的row.getItem()将返回SKU对象,并可以根据需要查看table2属性。
如果您真的不能做到这一点,那么一种方法就是维护一个ObservableMap<String, Double>,它将SKU映射到table2中显示的数量。这是一些工作,但也不算太糟:
ObservableMap<String, Double> skuAmountLookup = table2.getItems().stream().collect(
Collectors.toMap(Product::getSKU, Product::getAmount,
// the next argument is a merge function, which is used if there are two (or more) items
// in table2 with the same SKU. This function would replace the first value by the second.
// If the SKUs are unique it doesn't really matter what you have here...
(x, y) -> y,
() -> FXCollections.observableHashMap()));现在,您需要在表内容更改时保持地图更新:
table2.getItems().addListener((ListChangeListener.Change<? extends Product> change) -> {
// can just do skuAmountLookup.clear(); followed by skuAmountLookup.putAll(...)
// passing in the same data used above to initialize it
// That's pretty inefficient though, the following will just update what's needed.
// This assumes SKUs are unique in table 2:
while (change.next()) {
if (change.wasAdded()) {
change.getAddedSubList().forEach(product ->
skuAmountLookup.put(product.getSKU(), product.getAmount()));
}
if (change.wasRemoved()) {
change.getRemoved().forEach(product -> skuAmountLookup.remove(product.getSKU()));
}
}
});然后禁用条件可以类似于
row.disableProperty().bind(Bindings.createBooleanBinding(
() -> row.getItem() != null &&
skuAmountLookup.containsKey(row.getItem().getSKU()) &&
skuAmountLookup.get(row.getItem().getSKU()) < 0,
skuAmountLookup,
row.itemProperty()));我什么都没试过,但应该管用的。这里有两个假设:
https://stackoverflow.com/questions/26632292
复制相似问题