TornadoFX ListView 的样式背景

Styling background of TornadoFX ListView

是否可以设置 ListView 组件的样式,使 none 个元素具有阴影背景?

我不是这样的:

而是让它们的样式都像第一项、第三项、第五项等。

TIA

您需要创建一个具有非空背景的自定义 ListCell。执行此操作后,ListView 对选定行的自动颜色处理将不再正常工作。所以你必须自己处理。选择操作会将文本的颜色反转为白色,仅此而已。所以需要根据ListCell的“Selected”属性来设置单元格的背景色。在 Java 中,它看起来像这样:

    public class Sample1 extends Application {
    
        public static void main(String[] args) {
            launch(args);
        }
    
        @Override
        public void start(Stage primaryStage) {
            Scene scene = new Scene(new ListBackgroundWhite(), 300, 200);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    }
    
    public class ListBackgroundWhite extends ListView<String> {
    
        public ListBackgroundWhite() {
            super();
            setCellFactory(listView -> new WhiteListCell());
            setItems(FXCollections.observableArrayList("first line", "second line", "third line", "fourth line"));
        }
    
        static class WhiteListCell extends ListCell<String> {
    
        WhiteListCell() {
            Background unselectedBackground =
                    new Background(new BackgroundFill(Color.WHITESMOKE, CornerRadii.EMPTY, Insets.EMPTY));
            Background selectedBackground = new Background(new BackgroundFill(Color.BROWN, CornerRadii.EMPTY,
                    Insets.EMPTY));
            backgroundProperty().bind(Bindings.createObjectBinding(() -> isSelected() ? selectedBackground :
                    unselectedBackground, selectedProperty()));
        }
    
            @Override
            public void updateItem(String item, boolean isEmpty) {
                super.updateItem(item, isEmpty);
                if (!isEmpty) {
                    setText(item);
                } else {
                    setText(null);
                }
            }
        }
    }

执行此操作后,单元格背景不再透明,ListView 本身的条纹图案也不会显示出来。

编辑:

正如所指出的那样,这有点笨拙,除了在大多数情况下 ListView 不会是一个简单的带有字符串的标签。它将在 ListCell 中有某种布局,要求您在任何情况下创建自定义 ListCell。

但是,直接通过绑定到“选定”属性 来弄乱背景是笨拙的。您可以创建一个新的 StyleClass,然后在 css 中定义修改后的 PseudoClasses。然后将这个新的 StyleClass 添加到自定义 ListCell 中,然后它会在应用“EVEN”和“ODD”伪类时自动处理它。

我发现的一件事是,由于在默认 Modena css 中的所有其他定义之后应用了新的“奇数”定义,因此 ODD 行的“SELECTED”伪类被抑制了。这意味着奇数行和偶数行在被选中时看起来不同,因此需要在“ODD”定义之后将重复的“SELECTED”定义添加到新的 css 中。然后一切正常。所以新代码看起来像这样:

CSS:

.custom-list-cell:odd {
    -fx-background: -fx-control-inner-background;
}

.custom-list-cell:selected {
    -fx-background: -fx-selection-bar;
    -fx-table-cell-border-color: derive(-fx-selection-bar, 20%);
}

主体,现在将新样式表加载到场景中:

public class Sample1 extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        Scene scene = new Scene(new ListBackgroundWhite(), 300, 200);
        scene.getStylesheets().add(getClass().getResource("/css/samples.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

然后对 ListCell 的唯一自定义是添加新的 StyleClass:

public class ListBackgroundWhite extends ListView<String> {

    public ListBackgroundWhite() {
        super();
        setCellFactory(listView -> new WhiteListCell());
        setItems(FXCollections.observableArrayList("first line", "second line", "third line", "fourth line"));
    }

    static class WhiteListCell extends ListCell<String> {

        WhiteListCell() {
            getStyleClass().add("custom-list-cell");
        }

        @Override
        public void updateItem(String item, boolean isEmpty) {
            super.updateItem(item, isEmpty);
            if (!isEmpty) {
                setText(item);
            } else {
                setText(null);
            }
        }
    }
}

但如果您真的只想拥有一个只有简单标签的 ListView,您可以让单元工厂将 StyleClass 添加到标准 TextFieldListCell 中:

public ListBackgroundWhite() {
    super();
    setCellFactory(listView -> {
        ListCell<String> cell = new TextFieldListCell<>();
        cell.getStyleClass().add("custom-list-cell");
        return cell;
    });
    setItems(FXCollections.observableArrayList("first line", "second line", "third line", "fourth line"));
}

在默认样式表中,modena.css ListCell 的背景颜色由以下代码行控制:

.list-cell,
.tree-cell {
    -fx-background: -fx-control-inner-background;
    -fx-background-color: -fx-background;
    -fx-text-fill: -fx-text-background-color;
}

/* ... */

.list-cell:odd {
    -fx-background: -fx-control-inner-background-alt;
}

所以要删除奇数单元格的替代颜色(注意计数是从零开始的,所以奇数单元格是列表视图中的第 2 个、第 4 个等),您只需要包括外部 CSS 文件中的以下内容,将奇数单元格的颜色恢复为与偶数单元格相同的颜色:

.list-cell:odd {
    -fx-background: -fx-control-inner-background ;
}

如果您需要将此应用到一个特定的 ListView,您可以在该 ListView 上设置一个 ID:

ListView myListView ;
// ...

myListView.setId("plain-list-view");

然后 CSS 选择器变为

#plain-list-view .list-cell:odd {
    -fx-background: -fx-control-inner-background ;
}