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

标签 javafx javafx-8

我有以下问题:

我有ListView<ViewsRecord>哪里ViewsRecord有属性(property)int favorites 。 如果favorites > 0它在收藏夹中,如果 favorites == 0这是常规行(不是最喜欢的)。

现在我想做的是:

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

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

    2.2。如果单元格位于收藏夹中,则其背景为绿色

到目前为止,我想出了这个解决方案,但它的代码很丑陋,我想知道是否有最简单的方法来做到这一点。 此外,我不得不使用 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;
            }
        });

最佳答案

您可以使用 PseudoClass 根据最喜欢的属性来设置列表单元格的样式。

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 来设置列表单元格的样式:

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

关于javafx - 如何在选择和取消选择单元格时轻松自定义 JavaFX ListCell 背景颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36338725/

相关文章:

JavaFX 延迟绘制形状

java - 如何在JavaFX上绘制网格并用点绘制网格角?

JavaFX:位置未设置

javafx 简单的 PathTransition 动画

java - 如何最好在 XML 中序列化 JavaFX 节点?

java - 如何将两个项目添加到此可观察列表中?

javafx - Scenebuilder 2.0 中的自定义组件

java - Eclipse 中可运行 jar 文件出现问题 : Unable to construct Application instance

javafx-8 - 如何在 JavaFX 中通过单击按钮替换场景组件

java - 在哪里可以找到 combo-box-table-cell css 样式的规则?