当前位置: 首页 > 知识库问答 >
问题:

对象属性上的Javafx更新ListCell

慕阳
2023-03-14

我尝试了以下方法,但在编辑归档后,它会更改样式,但也会更改列表中其他ListCell的样式。

private ListView<ProviderProduct> importProductsListView  = //Set items in list
importProductsListView.setCellFactory(
    new Callback<ListView<ProviderProduct>, ListCell<ProviderProduct>>() {
        public ListCell<ProviderProduct> call(ListView<ProviderProduct> param) {
            final ListCell<ProviderProduct> cell = new ListCell<ProviderProduct>(){

                public void updateItem(ProviderProduct providerProduct, boolean empty){
                    super.updateItem(providerProduct, empty);

                        if(!empty) {
                            setText(providerProduct.toString());

                            if(providerProduct.hasPriceWarning()){
                                getStyleClass().add(Consts.CSS_ALERT);
                            }else{
                                getStyleClass().remove(Consts.CSS_ALERT);
                            }

                            providerProduct.priceListinoProperty().addListener(
                                new ChangeListener<BigDecimal>() {
                                    @Override
                                    public void changed(ObservableValue<? extends BigDecimal> observable,BigDecimal oldValue, BigDecimal newValue) {

                                        if(providerProduct.hasPriceWarning()){
                                            if(!getStyleClass().contains(Consts.CSS_ALERT)){
                                                getStyleClass().add(Consts.CSS_ALERT);
                                            }
                                        }else{
                                            getStyleClass().removeAll(Collections.singleton(Consts.CSS_ALERT));
                                        }
                                    }
                                });
                        }else{ 
                            setText("");
                            getStyleClass().remove(Consts.CSS_ALERT);
                        }
                   }
            };
            return cell;
        }
});

共有1个答案

岳英锐
2023-03-14

我可以看到您的代码存在两个问题:

首先,样式类由一个列表表示,它当然可以保存重复的条目。因此,如果您运气不好,将单元格从一个带有警告的项重用到另一个带有警告的项,那么最终将添加两次样式类。然后,remove(…)方法只删除一个副本,因此当您滚动列表时,您将开始看到不一致的行为。

如果你坚持使用JavaFX 2.2,你需要做以下事情:

if(providerProduct.hasPriceWarning() & ! getStyleClass().contains(Consts.CSS_ALERT){
    getStyleClass().add(Consts.CSS_ALERT);
}else{
    getStyleClass().remove(Consts.CSS_ALERT);
}

如果您真的想要防弹,确保您删除所有出现的方法是使用以下方法来代替您对删除(...)的调用:

getStyleClass().removeAll(Collections.singleton(CSS_ALERT));

如果您可以使用JavaFX 8(即java 8),那么您应该考虑使用“PseudoClass”来代替,这更容易,并且据说更有效。(另外,使用lambda代替所有这些匿名内部类将使代码更易于管理。)

其次,每当更新单元格时,您都会使用该项的相应属性注册一个侦听器。因此,当单元格被重用以表示一个新项目时(例如,当用户滚动列表时),它将侦听多个项目的属性。您需要根据需要安排删除侦听器。

我更愿意通过创建一个默认的ListCell并观察它的itemProperty(),来实现这一点,因为这样可以在它发生变化时清晰地访问旧项和新项。所以你可以这样做:

importProductsListView.setCellFactory(
    new Callback<ListView<ProviderProduct>, ListCell<ProviderProduct>>() {
        public ListCell<ProviderProduct> call(ListView<ProviderProduct> param) {
            final ListCell<ProviderProduct> cell = new ListCell<ProviderProduct>();

            final ChangeListener<BigDecimal> priceListener = new ChangeListener<BigDecimal>() {
                @Override
                public void changed(ObservableValue<? extends BigDecimal> observable,BigDecimal oldValue, BigDecimal newValue) {

                     if(providerProduct.hasPriceWarning()){
                         if(!getStyleClass().contains(Consts.CSS_ALERT)){
                              getStyleClass().add(Consts.CSS_ALERT);
                         }
                     }else{
                         getStyleClass().removeAll(Collections.singleton(Consts.CSS_ALERT));
                     }
                }
            });

            cell.itemProperty().addListener(new ChangeListener<ProviderProduct>() {
                @Override
                public void changed(ObservableValue<? extends ProviderProduct> obs, ProviderProduct oldProduct, ProviderProduct newProduct) {
                    if (oldProduct != null) {
                        oldProduct.priceListinoProperty().removeListener(priceListener);
                    }
                    if (newProduct == null) {
                        cell.setText(null);
                        cell.getStyleClass().removeAll(Collections.singleton(Consts.CSS_ALERT);
                    } else {
                        cell.setText(newProduct.toString());
                        if (newProduct.hasPriceWarning()) {
                            if (! cell.getStyleClass().contains(Consts.CSS_ALERT)) {
                                cell.getStyleClass().add(Consts.CSS_ALERT);
                            }
                        } else {
                            cell.getStyleClass().removeAll(Collections.singleton(Consts.CSS_ALERT));
                        }
                        newProduct.priceListinoProperty().addListener(priceListener);
                    }
                }
            });

            return cell ;
         }
});
 类似资料:
  • 我有一个包含很多字段的列表,需要使用stream在一次传递中创建一个列表。 > 我们需要将列表中的字段current标记为true,以获得输入列表中最小的正整数 输入: 输出: 我有点困惑,如何推导逻辑,将单个循环中最小正整数的当前标志(**)更新为true。

  • 问题内容: 我有一个像这样的JSON字符串: 我想将属性更新为,如果值为,并且值为。 我已经到了这一点,但是不确定如何进行: 我不知道怎么去的是一个孩子。 提前致谢。任何指针都很棒。 问题答案: 您可以使用属性作为键来访问对象: 对于您的示例,请尝试:

  • 下表(按对象名称排序)列出了 Microsoft Office 中已有对象添加的属性。对象属性CommandBarButton Mask Picture CommandBars DisableAskAQuestionDropdown DisableCustomizeFileDialog AllowMultiSelect ButtonName DialogType FilterIndex Filte

  • 问题内容: 我想在Qml中显示一个矩形,并且想从我的python代码中更改矩形的属性(宽度,长度)。实际上,在python代码中有一个套接字连接,通过该套接字连接可以从另一台计算机接收width和length的值。简而言之:另一个用户应该能够实时调整此矩形。我知道如何在我的python文件中建立套接字连接,并使用PyQt5,我可以显示来自python的qml文件。 但是,我在通过python代码访

  • 问题内容: 我有一个具有多个相关属性的类,例如: 如果我正常地制作一个对象,那没有问题, 我将得到2个列表,和。 现在,如果我想先创建一个空对象,并为其分配一个属性,则希望其他属性自动更新,例如 我想自动更新,也想自动更新(分配和自动更新)。这可能吗? Class 是否是正确的选择? 谢谢大家,但是所有其他答案让我完全不知所措。谁能提供一个完整的解决方案,让我可以学习编写自己的解决方案? 我想实现

  • 我有以下Java超类,每个属性都有构造函数、getter和setter: 和一个car子类,它扩展了vehicle超类,并具有几个独特的属性: 我创建一个新的vehicle对象链表,并向其中添加一个新的car对象: 我可以用下面这样的函数更改属于vehicle超级类的任何属性: 但是当我试图创建一个类似的函数来更改其中一个子类属性时,我得到了这个错误:“方法setWheels(int)对于类型Ve