我的TreeView由我自己的树填充。在类Node中,我有字段" type"这是NodeType之一。问题是我希望每种类型的NodeType都有样式,例如" TYPE1"文字颜色应为绿色," type2"文字颜色应为红色。我是javaFX的新手。我找到了james-d(https://github.com/james-d/heterogeneous-tree-example)的解决方案,但在这个例子中,css样式取决于类名,我怎样才能为类字段创建它?
答案 0 :(得分:0)
我的理解是,您希望TreeCell
的风格有所不同,具体取决于所述NodeType
的{{1}}中包含的Node
的{{1}}。全部通过CSS。我是对的吗?
假设我是正确的,我有两种方法可以实现这一点;如果存在少量已知TreeItem
s,则两者都能发挥最佳效果。第一个涉及使用PseudoClass,第二个使用与JavaFX TreeCell
API相同的策略。
创建适合使用NodeType
类型的自定义Chart
(即适当指定通用签名)。在此自定义TreeCell
中,您可以根据需要声明尽可能多的Node
个静态最终字段;每个TreeCell
一个。然后,您会观察PseudoClass
中当前显示的NodeType
NodeType
Node
并相应地更新TreeCell
个州。
以下示例假设PseudoClass
为NodeType
,其中包含两个常量:enum
和HAPPY
。
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,因为重写此方法需要开发人员处理某些事情(例如调用超级实现)。