如何在 Javafx 的 TreeView 中设置单元格的缩进
How to set cell's indentation in TreeView in Javafx
我正在做一个TreeView
,它代表一个机器人控制程序,每个TreeCell
代表一个语句,一个TreeCell
可以嵌套在另一个中。就像在编程中一样,语句可以嵌套在 if
或 for
语句中。
我在这里创建了一个简单的演示,其中填充了一些随机块。
Demo Screenshot
为了自定义 TreeCell
的渲染,我创建了一个 class 扩展 TreeCell
:
public class TreeDataCell extends TreeCell<TreeData> {
public void updateItem(TreeData item, boolean empty) {
super.updateItem(item, empty);
setText(null);
if (item == null || empty) {
setGraphic(null);
} else {
setGraphic(getCellGraphic(item));
}
}
private Group getCellGraphic(TreeData data) {
Group grp = new Group();
VBox vbox = new VBox();
vbox.setMinWidth(100);
vbox.setMaxWidth(200);
vbox.setBorder(new Border(new BorderStroke(
Color.LIGHTGRAY.darker(),
BorderStrokeStyle.SOLID,
new CornerRadii(10.0),
new BorderWidths(2.0))));
vbox.setBackground(new Background(new BackgroundFill(Color.LIGHTGRAY, new CornerRadii(10.0), null)));
vbox.setEffect(new DropShadow(2.0, 3.0, 3.0, Color.DIMGRAY));
Region header = new Region();
header.setPrefHeight(5.0);
Region footer = new Region();
footer.setPrefHeight(5.0);
Label labTitle = new Label();
labTitle.setFont(new Font("San Serif", 20));
labTitle.setText(data.getTitle());
Label labDesc = null;
if (data.getDescription() != null) {
labDesc = new Label();
labDesc.setWrapText(true);
labDesc.setText(data.getDescription());
}
vbox.getChildren().addAll(header, labTitle);
if (labDesc != null) {
vbox.getChildren().add(labDesc);
}
vbox.getChildren().add(footer);
grp.getChildren().add(vbox);
return grp;
}
}
TreeData
是一个简单的 class 包含 2 String
s:
public class TreeData {
private String title;
private String desc;
/* getters + setters */
}
如你所见,两层之间的缩进太小,几乎看不到语句嵌套。
我正在对 Java 中的所有样式进行硬编码,因为我还没有学习 FXML+CSS。
我想知道是否可以在Java中设置缩进的大小?为此,我找不到任何 API。另外,是否可以像Swing
中的JTree
那样在父节点和它的子节点之间画线?
谢谢。
关于像 JTree
中那样的行,从 JavaFX 11 开始没有内置的方法来做到这一点。有一个功能请求 (JDK-8090579),但似乎没有任何实施计划。您也许可以自己实现,但我不确定如何实现。
关于修改TreeCell
的缩进,最简单的方法是使用CSS.
如 JavaFX CSS Reference Guide, TreeCell
has a CSS property named -fx-indent
whose value is a <size>
. You can set this property by using a stylesheet or inline it via the style
property 中所述。使用内联样式的示例:
public class TreeDataCell extends TreeCell<TreeData> {
public TreeDataCell() {
setStyle("-fx-indent: <size>;");
}
}
但是,由于您当前没有使用 CSS 或 FXML,因此还有另一个纯代码的选项:修改 TreeCellSkin
的 indent
属性。这个 class 在 JavaFX 9 中变成了 public API。在 JavaFX 8 中可能有等效的内部 API 但我不确定。
默认情况下,TreeCell
的 Skin
将是 TreeCellSkin
的实例。这意味着您可以获得此皮肤并根据需要设置缩进值。但是,您必须小心,因为皮肤是懒惰创建的;它不一定可用,直到 TreeView
实际上是显示的一部分 window。
如果只想设置一次属性,一种方法是截取里面的皮肤createDefaultSkin()
:
public class TreeDataCell extends TreeCell<TreeData> {
@Override
protected Skin<?> createDefaultSkin() {
TreeCellSkin<?> skin = (TreeCellSkin<?>) super.createDefaultSkin();
skin.setIndent(/* your value */);
return skin;
}
}
您还可以扩展 TreeCellSkin
并自定义它。请记住覆盖 createDefaultSkin()
和 return 自定义皮肤实现。
我正在做一个TreeView
,它代表一个机器人控制程序,每个TreeCell
代表一个语句,一个TreeCell
可以嵌套在另一个中。就像在编程中一样,语句可以嵌套在 if
或 for
语句中。
我在这里创建了一个简单的演示,其中填充了一些随机块。
Demo Screenshot
为了自定义 TreeCell
的渲染,我创建了一个 class 扩展 TreeCell
:
public class TreeDataCell extends TreeCell<TreeData> {
public void updateItem(TreeData item, boolean empty) {
super.updateItem(item, empty);
setText(null);
if (item == null || empty) {
setGraphic(null);
} else {
setGraphic(getCellGraphic(item));
}
}
private Group getCellGraphic(TreeData data) {
Group grp = new Group();
VBox vbox = new VBox();
vbox.setMinWidth(100);
vbox.setMaxWidth(200);
vbox.setBorder(new Border(new BorderStroke(
Color.LIGHTGRAY.darker(),
BorderStrokeStyle.SOLID,
new CornerRadii(10.0),
new BorderWidths(2.0))));
vbox.setBackground(new Background(new BackgroundFill(Color.LIGHTGRAY, new CornerRadii(10.0), null)));
vbox.setEffect(new DropShadow(2.0, 3.0, 3.0, Color.DIMGRAY));
Region header = new Region();
header.setPrefHeight(5.0);
Region footer = new Region();
footer.setPrefHeight(5.0);
Label labTitle = new Label();
labTitle.setFont(new Font("San Serif", 20));
labTitle.setText(data.getTitle());
Label labDesc = null;
if (data.getDescription() != null) {
labDesc = new Label();
labDesc.setWrapText(true);
labDesc.setText(data.getDescription());
}
vbox.getChildren().addAll(header, labTitle);
if (labDesc != null) {
vbox.getChildren().add(labDesc);
}
vbox.getChildren().add(footer);
grp.getChildren().add(vbox);
return grp;
}
}
TreeData
是一个简单的 class 包含 2 String
s:
public class TreeData {
private String title;
private String desc;
/* getters + setters */
}
如你所见,两层之间的缩进太小,几乎看不到语句嵌套。
我正在对 Java 中的所有样式进行硬编码,因为我还没有学习 FXML+CSS。
我想知道是否可以在Java中设置缩进的大小?为此,我找不到任何 API。另外,是否可以像Swing
中的JTree
那样在父节点和它的子节点之间画线?
谢谢。
关于像 JTree
中那样的行,从 JavaFX 11 开始没有内置的方法来做到这一点。有一个功能请求 (JDK-8090579),但似乎没有任何实施计划。您也许可以自己实现,但我不确定如何实现。
关于修改TreeCell
的缩进,最简单的方法是使用CSS.
如 JavaFX CSS Reference Guide, TreeCell
has a CSS property named -fx-indent
whose value is a <size>
. You can set this property by using a stylesheet or inline it via the style
property 中所述。使用内联样式的示例:
public class TreeDataCell extends TreeCell<TreeData> {
public TreeDataCell() {
setStyle("-fx-indent: <size>;");
}
}
但是,由于您当前没有使用 CSS 或 FXML,因此还有另一个纯代码的选项:修改 TreeCellSkin
的 indent
属性。这个 class 在 JavaFX 9 中变成了 public API。在 JavaFX 8 中可能有等效的内部 API 但我不确定。
默认情况下,TreeCell
的 Skin
将是 TreeCellSkin
的实例。这意味着您可以获得此皮肤并根据需要设置缩进值。但是,您必须小心,因为皮肤是懒惰创建的;它不一定可用,直到 TreeView
实际上是显示的一部分 window。
如果只想设置一次属性,一种方法是截取里面的皮肤createDefaultSkin()
:
public class TreeDataCell extends TreeCell<TreeData> {
@Override
protected Skin<?> createDefaultSkin() {
TreeCellSkin<?> skin = (TreeCellSkin<?>) super.createDefaultSkin();
skin.setIndent(/* your value */);
return skin;
}
}
您还可以扩展 TreeCellSkin
并自定义它。请记住覆盖 createDefaultSkin()
和 return 自定义皮肤实现。