如何在Javafx的TreeView中设置单元格的缩进

时间:2018-11-16 08:07:55

标签: java javafx fxml

我正在研究TreeView,它代表一个机器人控制程序,每个TreeCell代表一条语句,并且TreeCell可以嵌套在另一个语句中。像在编程中一样,语句可以嵌套在iffor语句中。

在这里,我创建了一个简单的演示,其中填充了一些随机块。

Demo Screenshot

要自定义TreeCell的呈现方式,我创建了一个扩展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是一个简单的类,包含2个String

public class TreeData {
    private String title;
    private String desc;
    /* getters + setters */
}

如您所见,两个级别之间的缩进太小了,我们几乎看不到语句嵌套。

由于我还没有学习过FXML + CSS,所以我正在用Java编写所有样式的代码。

我想知道是否可以在Java中设置缩进大小?我找不到用于此目的的任何API。另外,是否可以像JTree中的Swing一样在父节点与其子节点之间画线?

谢谢。

1 个答案:

答案 0 :(得分:0)

关于在JTree中有这样的行,从JavaFX 11开始,没有内置的方法可以做到这一点。有一个功能请求(JDK-8090579),但似乎没有任何计划实施它。您也许可以自己实现它,但是我不确定如何实现。

关于修改TreeCell的缩进,最简单的方法是使用CSS。

JavaFX CSS Reference Guide中所述,TreeCell具有一个名为-fx-indent的CSS属性,其值为<size>。您可以使用样式表设置此属性,也可以通过style property内联该属性。使用内联样式的示例:

public class TreeDataCell extends TreeCell<TreeData> {

    public TreeDataCell() {
        setStyle("-fx-indent: <size>;");
    }

}

但是,由于您当前未使用CSS或FXML,所以还有另一个纯代码的选项:修改TreeCellSkinindent属性。该类在JavaFX 9中成为公共API。JavaFX8中可能有等效的内部API,但我不确定。

默认情况下,Skin的{​​{1}}将是TreeCell的实例。这意味着您可以获取此外观并根据需要设置缩进值。但是,由于皮肤是懒惰的,因此必须小心。在TreeCellSkin实际上是显示窗口的一部分之前,它不一定可用。

如果只想设置一次属性,一种方法是拦截TreeView内的皮肤:

createDefaultSkin()

您还可以扩展public class TreeDataCell extends TreeCell<TreeData> { @Override protected Skin<?> createDefaultSkin() { TreeCellSkin<?> skin = (TreeCellSkin<?>) super.createDefaultSkin(); skin.setIndent(/* your value */); return skin; } } 并对其进行自定义。只要记住要覆盖TreeCellSkin并返回自定义外观即可。