如何根据 JavaFX 中的条件设置列表视图单元格的样式

Phi*_*yyy 0 css java listview javafx

我试图根据条件设置列表视图中各个单元格的样式。列表视图的类型是Label,在列表视图中插入标签时,条件是根据另一个类确定的。

目前,我尝试设置列表视图中每个标签的背景颜色,但它没有覆盖整个区域(见图)。

在此输入图像描述

我也研究了这篇文章,但它不适合我的情况,因为字符串中不包含用于突出显示列表视图单元格的标识符。

如何动态更改 JavaFX 中列表视图中项目的背景

到目前为止的当前代码:

for (Consultation c : notifications){
            Label l = new Label(": consult reminder - "  + c.getReminderTime());

            if(c.getReminderRead() == 1){ //if the consultation reminder hasn't been read
                l.setStyle("-fx-background-color: #33CEFF");
                counter = counter + 1;
            }


            notificationList.getItems().add(l);
}
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Jam*_*s_D 5

Label使用节点子类(例如)作为、等控件的数据类型基本上总是错误的。(我能想到的唯一例外是,如果您正在编写 GUI 构建器,例如 Scene Builder,其中GUI 节点类的创建成本非常昂贵;数据确实是实际的 GUI 节点。它们通常具有数百个属性以及与样式和 CSS 解析、事件侦听器等相关的大量开销。将其与您的实际数据类进行比较,它可能具有十几个属性或更少,并且没有其他开销。如果您使用一种或其他节点类作为 的数据类型,则可以为列表中的每一项创建一个节点a 的全部要点是它只为每个可见单元创建节点,并重用这些单元。因此,如果您有一个很大的列表,您的方法可能会导致性能问题。(另一点是,您违反了视图(表示)与模型(数据)的分离。)ListViewTableViewConsultationLabelListViewListView

所以你真的应该有一个ListView<Consultation>这里,并使用单元工厂来配置单元格的文本和样式:

ListView<Consultation> notificationList = ... ;

notificationList.setCellFactory(lv -> new ListCell<Consultation>() {
    @Override
    protected void updateItem(Consultation c, boolean empty) {
        super.updateItem(c, empty);
        if (empty) {
            setText(null);
            setStyle("");
        } else {
            setText(": consult reminder - "  + c.getReminderTime());

            // Are you REALLY using an int for the reminderRead property??!?
            // Surely this should be a boolean...

            if (c.getReminderRead() == 1) { // I feel dirty just writing that
                setStyle("-fx-background-color: #33CEFF");
            } else {
                setStyle("");
            }
        }
    }
});

notificationList.getItems().setAll(notifications);
Run Code Online (Sandbox Code Playgroud)

将样式分解到外部 CSS 文件中会更好一些。您可以使用 CSS PseudoClass 来打开和关闭不同的样式:

ListView<Consultation> notificationList = ... ;

PseudoClass reminderRead = PseudoClass.getPseudoClass("reminder-read");

notificationList.setCellFactory(lv -> new ListCell<Consultation>() {
    @Override
    protected void updateItem(Consultation c, boolean empty) {
        super.updateItem(c, empty);
        if (empty) {
            setText(null);
        } else {
            setText(": consult reminder - "  + c.getReminderTime());
        }

        // assumes Consultation.getReminderRead() returns a boolean...
        pseudoClassStateChanged(reminderRead, c != null && c.getReminderRead())
    }
});

notificationList.getItems().setAll(notifications);
Run Code Online (Sandbox Code Playgroud)

现在,在您的外部 CSS 文件中,您可以执行以下操作:

ListView<Consultation> notificationList = ... ;

notificationList.setCellFactory(lv -> new ListCell<Consultation>() {
    @Override
    protected void updateItem(Consultation c, boolean empty) {
        super.updateItem(c, empty);
        if (empty) {
            setText(null);
            setStyle("");
        } else {
            setText(": consult reminder - "  + c.getReminderTime());

            // Are you REALLY using an int for the reminderRead property??!?
            // Surely this should be a boolean...

            if (c.getReminderRead() == 1) { // I feel dirty just writing that
                setStyle("-fx-background-color: #33CEFF");
            } else {
                setStyle("");
            }
        }
    }
});

notificationList.getItems().setAll(notifications);
Run Code Online (Sandbox Code Playgroud)