[英]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样式取决于类名,如何在类字段中使用它呢?
我的理解是,您想要一个TreeCell
,其样式取决于包含在所说TreeCell
的TreeItem
中的Node
的NodeType
。 全部通过CSS。 我对么?
假设我是对的,我可以想到两种方法来完成此任务; 如果存在少量已知的NodeType
,则两者都最有效。 第一种使用PseudoClass ,第二种使用与JavaFX Chart
API相同的策略。
创建一个定制的TreeCell
,它适合使用您的Node
类型(即,适当地指定通用签名)。 在此自定义TreeCell
您可以根据需要声明多个PseudoClass
静态final字段; 每个NodeType
。 然后,您观察TreeCell
当前显示的任何Node
的NodeType
并相应地更新PseudoClass
状态。
这是一个示例,假设NodeType
是具有两个常量的enum
: HAPPY
和SAD
。
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.