繁体   English   中英

JavaFX TreeItem CSS样式用于不同的类字段

[英]JavaFX TreeItem css style for different class field

我有自己的树填充的TreeView。 在节点类中,我具有字段“类型”,它是NodeType之一。 问题是我希望每种类型的NodeType都有样式,例如“ type1”文本颜色应为绿色,“ type2”文本颜色应为红色。 我是javaFX的新手。 我通过james-d( https://github.com/james-d/heterogeneous-tree-example )找到了解决方案,但是在此示例中,css样式取决于类名,如何在类字段中使用它呢?

TreeView的视图

我的理解是,您想要一个TreeCell ,其样式取决于包含在所说TreeCellTreeItem中的NodeNodeType 全部通过CSS。 我对么?

假设我是对的,我可以想到两种方法来完成此任务; 如果存在少量已知的NodeType ,则两者都最有效。 第一种使用PseudoClass ,第二种使用与JavaFX Chart API相同的策略。


第一选择

创建一个定制的TreeCell ,它适合使用您的Node类型(即,适当地指定通用签名)。 在此自定义TreeCell您可以根据需要声明多个PseudoClass静态final字段; 每个NodeType 然后,您观察TreeCell当前显示的任何NodeNodeType并相应地更新PseudoClass状态。

这是一个示例,假设NodeType是具有两个常量的enumHAPPYSAD

public class CustomTreeCell<T extends Node> extends TreeCell<T> {

    private static final PseudoClass HAPPY = PseudoClass.getPseudoClass("happy");
    private static final PseudoClass SAD = PseudoClass.getPseudoClass("sad");

    // this listener will activate/deactivate the appropriate PseudoClass states
    private final ChangeListener<NodeType> listener = (obs, oldVal, newVal) -> {
        pseudoClassStateChanged(HAPPY, newVal == NodeType.HAPPY);
        pseudoClassStateChanged(SAD, newVal == NodeType.SAD);
    };

    // use a weak listener to avoid a memory leak
    private final WeakChangeListener<NodeType> weakListener = /* wrap listener */;

    public CustomTreeCell() {
        getStyleClass().add("custom-tree-cell");
        itemProperty().addListener((obs, oldVal, newVal) -> {
            if (oldVal != null) {
                oldVal.nodeTypeProperty().removeListener(weakListener);
            }
            if (newVal != null) {
                newVal.nodeTypeProperty().addListener(weakListener);
                // need to "observe" the initial NodeType of the new Node item.
                // You could call the listener manually to avoid code duplication
                pseudoClassStateChanged(HAPPY, newVal.getNodeType() == NodeType.HAPPY);
                pseudoClassStateChanged(SAD, newVal.getNodeType() == NodeType.SAD);
            } else {
                // no item in this cell so deactivate all PseudoClass's
                pseudoClassStateChanged(HAPPY, false);
                pseudoClassStateChanged(SAD, false);
            }
        });
    }
}

然后在您的CSS文件中可以使用:

.custom-tree-cell:happy {
    /* style when happy */
}

.custom-tree-cell:sad {
    /* style when sad */
}

第二选择

处理多个数据系列时,请执行JavaFX Chart API的操作。 它的作用是根据列表中系列的索引来动态更新节点的style class (例如, .line-chart-series-data-<index> <-可能不完全是这样)。

/*
 * Create a custom TreeCell like in the first option but
 * without any of the PseudoClass code. This listener should
 * be added/removed from the Node item just like weakListener
 * is above.
 */
ChangeListener<NodeType> listener = (obs, oldVal, newVal) -> {
    // You have to make sure you keep "cell", "indexed-cell", and "tree-cell"
    // in order to keep the basic modena styling.
    if (newVal == NodeType.HAPPY) {
        getStyleClass().setAll("cell", "indexed-cell", "tree-cell", "custom-tree-cell-happy");
    } else if (newVal == NodeType.HAPPY) {
        getStyleClass().setAll("cell", "indexed-cell", "tree-cell", "custom-tree-cell-sad");
    } else {
        getStyleClass().setAll("cell", "indexed-cell", "tree-cell"); // revert to regular TreeCell style
    }
};

然后在CSS中:

.custom-tree-cell-happy {
    /* styles */
}

.custom-tree-cell-sad {
   /* styles */
}

这两个选项实际上仅在只有少量已知类型的情况下才可行。 当您拥有10+ NodeType的东西时,它可能变得难以维护。 如果NodeType的数目在运行时是动态的,则几乎是不可能的。

NodeType或某些中间类/数据结构了解文本应为哪种颜色,并根据NodeType编程设置颜色可能会更容易。

注意:我很快在答案中输入了代码,但没有对其进行测试。 我的代码中可能存在编译器错误,运行时异常或逻辑错误。


编辑

我想到了别的东西。 上面的代码假定NodeType被保存在一个属性中,并且可以在运行时进行更改。 如果每个Node NodeType都是静态的(不变),则可以大大简化代码。 除了使用任何侦听器之外,您还可以简单地覆盖javafx.scene.control.Cell声明的以下方法:

protected void updateItem(Node item, boolean empty)

每次在单元格上设置新项目时,都会调用此方法。 但是,请阅读文档 ,因为重写此方法需要开发人员进行某些操作(例如,调用超级实现)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM