【问题标题】:Styling background of TornadoFX ListViewTornadoFX ListView 的样式背景
【发布时间】:2020-12-22 03:18:17
【问题描述】:

是否可以设置 ListView 组件的样式,使所有元素都没有阴影背景?

我不是这样的:

而是将它们都设置为第一个、第三个、第五个项目等样式。

TIA

【问题讨论】:

  • 从 css 中移除均匀样式?
  • 具体来说,我认为你需要的CSS是list-cell:odd { -fx-background: -fx-control-inner-background ;}

标签: kotlin javafx tornadofx


【解决方案1】:

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

.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 ;
}

【讨论】:

  • 我知道我需要将 listCell and odd 的案例添加到我的 Styles.kt 中,但是如何访问内部背景?还是我做错了?
  • @BenDent 我不明白这个问题。只需将最后一个代码块放在您的外部样式表(CSS 文件)中。我不使用 Kotlin,但假设您像在 Java 中一样将样式表添加到 Scene
【解决方案2】:

您需要创建一个具有非空背景的自定义 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 不会是一个简单的 Label ,其中包含一个字符串。它将在 ListCell 中进行某种布局,这将要求您在任何情况下都创建一个自定义 ListCell。

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

我发现的一件事是,由于在默认 Modena css 中的所有其他定义之后应用了新的“奇数”定义,因此奇数行的“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"));
}

【讨论】:

  • 这似乎有点过头了。我认为你可以用 CSS 做到这一点?
  • 你是对的,但是如果你通过css中的“list-cell”样式类来改变它,那么它会改变场景中的每个ListView(或每个使用该样式表的场景) .我已经更新了我的答案以正确使用 PseudoClasses,但不会弄乱通用样式。
  • 如果需要,您可以通过 CSS 选择器使其特定于一个列表视图(或一组特定的列表视图)
猜你喜欢
  • 1970-01-01
  • 2012-10-16
  • 2013-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-17
相关资源
最近更新 更多