如何在选择和取消选择单元格时轻松自定义JavaFX ListCell背景颜色

时间:2016-03-31 16:20:28

标签: javafx javafx-8

我有以下问题:

ListView<ViewsRecord>其中ViewsRecord有财产int favorites。 如果favorites > 0在收藏夹中,并且favorites == 0它是常规行(不是最喜欢的)。

现在我想做的是:

  1. 当用户选择单元格时(在多选模式下),这些单元格将具有默认选定的背景(例如:-fx-background-color: -fx-selection-bar))
  2. 当用户未选择单元格时:

    2.1。如果单元格不在收藏夹中,则它具有常规的bacground(例如白色)

    2.2。如果单元格在收藏夹中,则它具有绿色背景

  3. 到目前为止,我提出了这个解决方案,但它的代码很丑陋,我想知道是否有最简单的方法。 此外,我不得不使用setUserData()来检查是否应该选择单元格,否则在列表滚动期间或选择 - 单元格随机更改其颜色。 (我假设它是因为可重用对象存储在内存中而且updateItem()并不总是被触发)。

    这是我的代码:

    list.setCellFactory(new Callback<ListView<ViewsRecord>, ListCell<ViewsRecord>>(){
                @Override
                public ListCell<ViewsRecord> call(ListView<ViewsRecord> param) {
                    ListCell<ViewsRecord> cell = new ListCell<ViewsRecord>(){
                             @Override
                            protected void updateItem(ViewsRecord item, boolean empty) {
                                super.updateItem(item, empty);
                                if(!empty){
                                    if(item.getFavorites() > 0){  //favorite view
                                        if(!isSelected()){
                                            setStyle("-fx-background-color: darkseagreen;");
                                        }
                                        setUserData(new Integer(1));
                                    } else {  //normal view
                                        if(!isSelected()){
                                            setStyle("-fx-background-color: white;");
                                        }
                                        setUserData(new Integer(0));
                                    }
                                    setText(item.toString());
                                } else { //empty view
                                    setText(null); 
                                    setStyle("-fx-background-color: white;");
                                    setUserData(new Integer(0)); 
                                }
                            }
                        };
                    //fix bacground color when cell is selected
                    cell.selectedProperty().addListener( (obsVal, oldVal, newVal) -> {
                        if(newVal){
                            cell.setStyle("-fx-background-color: -fx-selection-bar;");
                        } else {
                            if((Integer)cell.getUserData() == 1){ //favorite
                                cell.setStyle("-fx-background-color: darkseagreen;");
                            } else { //normal
                                cell.setStyle("-fx-background-color: white;");
                            }
                        }
                    });
                    return cell;
                }   
            });
    

    修改

    感谢 jns ,我设法简化了代码。 当前版本:

    list.setCellFactory(new Callback<ListView<ViewsRecord>, ListCell<ViewsRecord>>(){   
                @Override
                public ListCell<ViewsRecord> call(ListView<ViewsRecord> param) {
                    final PseudoClass FAVORITE_PSEUDO_CLASS = PseudoClass.getPseudoClass("favorite");
                    ListCell<ViewsRecord> cell = new ListCell<ViewsRecord>(){
                             @Override
                            protected void updateItem(ViewsRecord item, boolean empty) {
                                if(!empty){
                                    //favorite or not, and not selected
                                    pseudoClassStateChanged(FAVORITE_PSEUDO_CLASS, (item.getFavorites() > 0) && !isSelected());
                                    setText(item.toString());
                                } else { 
                                    setText(null); 
                                    //empty
                                    pseudoClassStateChanged(FAVORITE_PSEUDO_CLASS, false);
                                }
                                super.updateItem(item, empty);
                             }
                    };
                    cell.selectedProperty().addListener( (obsVal, oldVal, newVal) -> {
                        if(newVal){
                            //selected
                            cell.pseudoClassStateChanged(FAVORITE_PSEUDO_CLASS, false); 
                        } else {
                            //favorite or not
                            cell.pseudoClassStateChanged(FAVORITE_PSEUDO_CLASS, cell.getItem().getFavorites() > 0); 
                        }
                    });
                    return cell;
                }
            });
    

2 个答案:

答案 0 :(得分:1)

您可以使用PseudoClass根据favorite属性设置listcell的样式。

public class YourListCell extends ListCell<ViewsRecord> {

private static PseudoClass FAVORITE_PSEUDO_CLASS = PseudoClass.getPseudoClass("favorite");

    @Override
     protected void updateItem(ViewsRecord item, boolean empty) {
         super.updateItem(item, empty);
         if (!empty) {
             boolean isFavorite = item > 0;              
             pseudoClassStateChanged(FAVOURITE_PSEUDO_CLASS, isFavorite);
             ...
     }
}

这允许您通过样式表中的css设置listcell的样式:

.list-cell:favorite {
-fx-background-color: darkseagreen;
}

答案 1 :(得分:1)

ListCell包含getItem()方法。因此,您可以访问您的数据对象。此外,您可以使用其PseudoClass为空并选择将更多样式处理传输到样式表:

.list-cell, .list-cell:empty {
    -fx-background-color: white
    }

.list-cell:favorite{
    -fx-background-color: darkseagreen;
}

.list-cell:selected {
    -fx-background-color: -fx-selection-bar;
}