当你有一个CellFactory时,如何在更改root时完全重置TreeView?

时间:2015-01-12 14:19:19

标签: java javafx javafx-8 fxml

这是this question的后续......这里转载的FXML文件:

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
    minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0"
    xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
    fx:id="pane"
    fx:controller="com.github.parboiled1.grappa.debugger.mainwindow.MainWindowUi">
    <top>
        <MenuBar BorderPane.alignment="CENTER">
            <Menu mnemonicParsing="false" text="File">
                <MenuItem fx:id="loadInput" mnemonicParsing="false"
                    text="Load file" onAction="#loadFileEvent"/>
                <MenuItem fx:id="parse" mnemonicParsing="false"
                    text="Parse" onAction="#parseEvent"/>
                <MenuItem fx:id="closeButton" mnemonicParsing="false"
                    text="Close" onAction="#closeWindowEvent"/>
            </Menu>
        </MenuBar>
    </top>
    <center>
        <SplitPane dividerPositions="0.5" prefHeight="160.0" prefWidth="200.0"
            BorderPane.alignment="CENTER">
            <SplitPane dividerPositions="0.5" orientation="VERTICAL">
                <TreeView fx:id="traceTree" prefHeight="200.0"
                    prefWidth="200.0" editable="false"/>
                <TextArea fx:id="traceDetail" prefHeight="200.0"
                    prefWidth="200.0"/>
            </SplitPane>
            <TextArea fx:id="inputText" prefHeight="200.0" prefWidth="200.0"/>
        </SplitPane>
    </center>
</BorderPane>

从那时起我改变了视图的类型,现在我有一个CellFactory来生成单元格并插入鼠标单击事件。它有效:

public final class ParseNodeCellFactory
    implements Callback<TreeView<MatchResult>, TreeCell<MatchResult>>
{
    private final MainWindowPresenter presenter;

    public ParseNodeCellFactory(final MainWindowPresenter presenter)
    {
        this.presenter = presenter;
    }

    @Override
    public TreeCell<MatchResult> call(final TreeView<MatchResult> param)
    {
        final ParsingTreeCell cell = new ParsingTreeCell();
        final EventHandler<MouseEvent> handler
            = event -> presenter.handleMatchResult(cell.getTreeItem());
        cell.setOnMouseClicked(handler);
        return cell;
    }

    private static final class ParsingTreeCell
        extends TreeCell<MatchResult>
    {
        @Override
        protected void updateItem(final MatchResult item, final boolean empty)
        {
            super.updateItem(item, empty);
            if (!empty)
                setText(item.getLabel() + " ("
                    + (item.isSuccess() ? "SUCCESS" : "FAILURE") + ')');
        }
    }
}

但是,我有两个问题:

  • 当我展开/折叠部分树时,给定的单元格不会自动隐藏;
  • TreeView必须在每次运行时完全重置。

我不知道如何解决这两个问题......

现在我有了这段代码(ui是对JavaFX控制器的引用):

@Override
public void setParseTree(final TreeItem<MatchResult> root)
{
    clearTraceTree();
    ui.traceTree.setRoot(root);
}

private void clearTraceTree()
{
    final TreeItem<MatchResult> root = ui.traceTree.getRoot();
    if (root != null) {
        clearChildren(root);
        ui.traceTree.setRoot(null);
    }
}

private void clearChildren(final TreeItem<MatchResult> item)
{
    final ObservableList<TreeItem<MatchResult>> children
        = item.getChildren();

    children.forEach(this::clearChildren);
    children.clear();
}

虽然这清除了清单,但问题是我之前已经扩展的旧单元仍然可见;我想完全抓住它们,并将重点放在当前拥有它的任何单元格上。怎么做?

另外,如何在加载新根时将焦点设置在根单元格上?

1 个答案:

答案 0 :(得分:2)

您的TreeCell无法处理空单元格的情况。因此,当您从树中删除所有内容时,您的单元格(变为空)将不会更新。类似地,当您折叠树中的节点时。

你需要

private static final class ParsingTreeCell
    extends TreeCell<MatchResult>
{
    @Override
    protected void updateItem(final MatchResult item, final boolean empty)
    {
        super.updateItem(item, empty);
        if (empty) {
            setText(null);
        } else {
            setText(item.getLabel() + " ("
                + (item.isSuccess() ? "SUCCESS" : "FAILURE") + ')');
        }
    }
}

要重置树,您可能只需要执行

root.getChildren().clear();