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

时间:2018-03-23 07:59:57

标签: java css javafx javafx-8

我的TreeView由我自己的树填充。在类Node中,我有字段" type"这是NodeType之一。问题是我希望每种类型的NodeType都有样式,例如" TYPE1"文字颜色应为绿色," type2"文字颜色应为红色。我是javaFX的新手。我找到了james-d(https://github.com/james-d/heterogeneous-tree-example)的解决方案,但在这个例子中,css样式取决于类名,我怎样才能为类字段创建它?

View of TreeView

1 个答案:

答案 0 :(得分:0)

我的理解是,您希望TreeCell的风格有所不同,具体取决于所述NodeType的{​​{1}}中包含的Node的{​​{1}}。全部通过CSS。我是对的吗?

假设我是正确的,我有两种方法可以实现这一点;如果存在少量已知TreeItem s,则两者都能发挥最佳效果。第一个涉及使用PseudoClass,第二个使用与JavaFX TreeCell API相同的策略。

第一个选项

创建适合使用NodeType类型的自定义Chart(即适当指定通用签名)。在此自定义TreeCell中,您可以根据需要声明尽可能多的Node个静态最终字段;每个TreeCell一个。然后,您会观察PseudoClass中当前显示的NodeType NodeType Node并相应地更新TreeCell个州。

以下示例假设PseudoClassNodeType,其中包含两个常量:enumHAPPY

SAD

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

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

第二选项

执行JavaFX .custom-tree-cell:happy { /* style when happy */ } .custom-tree-cell:sad { /* style when sad */ } API处理多个数据系列时所执行的操作。它的作用是动态更新节点的Chart,具体取决于列表中的系列索引(例如style class&lt; - 可能不是完全这个)。

.line-chart-series-data-<index>

然后在CSS中:

/*
 * 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
    }
};

当存在少量已知类型时,这两个选项实际上都是可行的。当你有10 + .custom-tree-cell-happy { /* styles */ } .custom-tree-cell-sad { /* styles */ } 之类的东西时,它可能变得不可维护。如果NodeType的数量在运行时是动态的,那么几乎不可能。

NodeType或某些中间类/数据结构知道文本应该是什么颜色并根据NodeType以编程方式设置颜色可能更容易。

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

修改

还有其他想法。我上面的代码假定NodeType保存在属性中,并且可以在运行时更改。如果NodeType对于每个NodeType是静态的(不变),那么代码可以大大简化。您可以简单地覆盖Node中声明的以下方法,而不是使用任何侦听器:

javafx.scene.control.Cell

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