拥有 CellFactory 时如何在更改根时完全重置 TreeView?
How to completely reset a TreeView when changing the root when you have a CellFactory?
这是 的后续内容...转载于此处的 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") + ')');
}
}
}
但是,我有两个问题:
- 当我 expand/collapse 部分树时,给定的单元格不会自动隐藏;
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();
}
虽然这清除了列表,但问题是我事先展开的旧单元格仍然可见;我想完全划掉它们,并清除当前拥有它的任何单元格上的焦点。怎么做?
此外,加载新根时如何将焦点设置在根单元格上?
您的 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();
这是
<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") + ')');
}
}
}
但是,我有两个问题:
- 当我 expand/collapse 部分树时,给定的单元格不会自动隐藏;
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();
}
虽然这清除了列表,但问题是我事先展开的旧单元格仍然可见;我想完全划掉它们,并清除当前拥有它的任何单元格上的焦点。怎么做?
此外,加载新根时如何将焦点设置在根单元格上?
您的 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();