【问题标题】:JavaFx list View coloring the list cellJavaFx 列表视图着色列表单元格
【发布时间】:2017-12-17 11:33:02
【问题描述】:

我有一个标签列表视图,我想在运行时为列表单元格着色。问题是我想用颜色填充整个单元格,而不仅仅是标签的背景。有没有办法在 Java/CSS 中做到这一点?

【问题讨论】:

标签: listview user-interface javafx listcellrenderer


【解决方案1】:

了解 ListView 单元格着色的动态特性

通常,内部单元格的颜色会根据许多因素而变化:

  1. 单元格是奇数行还是偶数行(偶数行的背景较浅)。
  2. 是否选择了行。
  3. 所选行具有不同的颜色,具体取决于控件是否具有焦点(聚焦的选定行为蓝色,未聚焦的选定行为灰色)。

因此,由于单元格颜色可以根据状态而变化,因此您需要在为单元格设置自定义颜色时决定是否要保留此行为。

示例解决方案

这是一个示例,它将根据列表项是否符合条件(在这种情况下为测试目的硬编码为以字母“J”开头的名称)将单元格颜色设置为浅绿色。

import javafx.application.Application;
import javafx.collections.*;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

public class ColoredList extends Application {
    private static final ObservableList<String> data = FXCollections.observableArrayList(
            "Jill",
            "Jack",
            "Tom",
            "Harry",
            "Jenney"
    );

    private static final String DEFAULT_CONTROL_INNER_BACKGROUND = "derive(-fx-base,80%)";
    private static final String HIGHLIGHTED_CONTROL_INNER_BACKGROUND = "derive(palegreen, 50%)";

    @Override
    public void start(Stage stage) throws Exception {
        ListView<String> listView = new ListView<>(data);
        listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
            @Override
            public ListCell<String> call(ListView<String> param) {
                return new ListCell<String>() {
                    @Override
                    protected void updateItem(String item, boolean empty) {
                        super.updateItem(item, empty);

                        if (item == null || empty) {
                            setText(null);
                            setStyle("-fx-control-inner-background: " + DEFAULT_CONTROL_INNER_BACKGROUND + ";");
                        } else {
                            setText(item);
                            if (item.startsWith("J")) {
                                setStyle("-fx-control-inner-background: " + HIGHLIGHTED_CONTROL_INNER_BACKGROUND + ";");
                            } else {
                                setStyle("-fx-control-inner-background: " + DEFAULT_CONTROL_INNER_BACKGROUND + ";");
                            }
                        }
                    }
                };
            }
        });

        VBox layout = new VBox(listView);
        layout.setPadding(new Insets(10));

        stage.setScene(new Scene(layout));
        stage.show();
    }

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

注意事项:

  1. 自定义单元格呈现是通过 ListView 的自定义单元格工厂完成的。
  2. 单元格工厂返回的单元格,根据单元格状态设置-fx-control-inner-background 查找的 CSS 颜色。如果您不知道查找颜色是什么,请在 JavaFX CSS reference guide 中查找,并查看 Java 安装附带的 jfxrt.jar 文件中的 modena.css 文件。
  3. 默认的单元格呈现机制会根据您的自定义颜色稍微加深或减轻 ListView 中的偶数行和奇数行。
  4. 该示例仅为未选择的行设置自定义颜色。对于选定的行,将保留默认的蓝色和灰色。因此,该示例并不全面,但希望为您提供足够的信息来完成您想要的工作。
  5. 示例在代码中对默认颜色和自定义颜色进行了编码,但较大的应用程序最好在单独的用户 CSS 样式表中定义这些颜色。

【讨论】:

  • 我认为这会创建一个新的自定义列表。所以每次调用它都会迭代列表的大小,效率不高。我需要一些改变特定单元格背景而不遍历整个列表的东西。
  • 代码效率相当高,只有在相关节点内容失效时visible nodes are updated
【解决方案2】:

在您的细胞工厂的updateItem 函数中,只需使用以下几行:

if(getIndex() % 2 == 1)
    setStyle("-fx-background-color: #AAAAAA");
else
    setStyle("");

【讨论】:

    猜你喜欢
    • 2016-05-05
    • 1970-01-01
    • 2019-08-18
    • 2012-11-21
    • 2017-07-23
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    • 2015-11-30
    相关资源
    最近更新 更多