TreeView 的占位符?
Placeholder for TreeView?
我有一个开始时为空的 TreeView,我想设置一个占位符直到它为空。就像可用于 ListView 的那个 (setPlaceholder())
我的第一个想法是将 TreeView 包装到 BorderPane 中,然后根据 TreeView 中元素的数量更改中心。问题是虽然我通过拖放将元素添加到 TreeView,并且如果我将标签设置到中心以替换占位符,我将无法再将我的项目拖放到 TreeView 中。任何建议将不胜感激。
TreeView 不支持占位符 - 不完全确定,为什么不,但可能是空树(不管这意味着什么:空根?没有 children 的根?根不显示?)是一种稀有物种.
不过,通过遵循支持它的虚拟化控件 f.i 的实现,实现起来相当简单。表视图。我们只需要一个自定义的 TreeViewSkin
- 管理(根据需要创建并添加到树的层次结构和布局)占位符
- 监听树的相关状态并适当更新占位符的可见性
一个例子,通过按钮在 null/not null 之间切换树的根来切换空:
public class TreeViewWithPlaceholder extends Application {
private static class TreeViewPlaceholderSkin<T> extends TreeViewSkin<T> {
private StackPane placeholderRegion;
private Label placeholderLabel;
public TreeViewPlaceholderSkin(TreeView<T> control) {
super(control);
installPlaceholderSupport();
}
private void installPlaceholderSupport() {
registerChangeListener(getSkinnable().rootProperty(), e -> updatePlaceholderSupport());
updatePlaceholderSupport();
}
/**
* Updating placeholder/flow visibilty depending on whether or not the tree
* is considered empty.
*
* Basically copied from TableViewSkinBase.
*/
private void updatePlaceholderSupport() {
if (isTreeEmpty()) {
if (placeholderRegion == null) {
placeholderRegion = new StackPane();
placeholderRegion.getStyleClass().setAll("placeholder");
getChildren().add(placeholderRegion);
placeholderLabel = new Label("No treeItems");
placeholderRegion.getChildren().setAll(placeholderLabel);
}
}
getVirtualFlow().setVisible(!isTreeEmpty());
if (placeholderRegion != null)
placeholderRegion.setVisible(isTreeEmpty());
}
@Override
protected void layoutChildren(double x, double y, double w, double h) {
super.layoutChildren(x, y, w, h);
if (placeholderRegion != null && placeholderRegion.isVisible()) {
placeholderRegion.resizeRelocate(x, y, w, h);
}
}
private boolean isTreeEmpty() {
return getSkinnable().getRoot() == null;
}
}
private Parent createContent() {
TreeView<String> tree = new TreeView<>() {
@Override
protected Skin<?> createDefaultSkin() {
return new TreeViewPlaceholderSkin<>(this);
}
};
Button toggle = new Button("toggleRoot");
toggle.setOnAction(e -> {
TreeItem<String> root = tree.getRoot();
tree.setRoot(root == null ? new TreeItem<>("root") : null);
});
BorderPane content = new BorderPane(tree);
content.setBottom(toggle);
return content;
}
@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
//stage.setTitle(FXUtils.version());
stage.show();
}
public static void main(String[] args) {
launch(args);
}
@SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(TreeViewWithPlaceholder.class.getName());
}
我有一个开始时为空的 TreeView,我想设置一个占位符直到它为空。就像可用于 ListView 的那个 (setPlaceholder())
我的第一个想法是将 TreeView 包装到 BorderPane 中,然后根据 TreeView 中元素的数量更改中心。问题是虽然我通过拖放将元素添加到 TreeView,并且如果我将标签设置到中心以替换占位符,我将无法再将我的项目拖放到 TreeView 中。任何建议将不胜感激。
TreeView 不支持占位符 - 不完全确定,为什么不,但可能是空树(不管这意味着什么:空根?没有 children 的根?根不显示?)是一种稀有物种.
不过,通过遵循支持它的虚拟化控件 f.i 的实现,实现起来相当简单。表视图。我们只需要一个自定义的 TreeViewSkin
- 管理(根据需要创建并添加到树的层次结构和布局)占位符
- 监听树的相关状态并适当更新占位符的可见性
一个例子,通过按钮在 null/not null 之间切换树的根来切换空:
public class TreeViewWithPlaceholder extends Application {
private static class TreeViewPlaceholderSkin<T> extends TreeViewSkin<T> {
private StackPane placeholderRegion;
private Label placeholderLabel;
public TreeViewPlaceholderSkin(TreeView<T> control) {
super(control);
installPlaceholderSupport();
}
private void installPlaceholderSupport() {
registerChangeListener(getSkinnable().rootProperty(), e -> updatePlaceholderSupport());
updatePlaceholderSupport();
}
/**
* Updating placeholder/flow visibilty depending on whether or not the tree
* is considered empty.
*
* Basically copied from TableViewSkinBase.
*/
private void updatePlaceholderSupport() {
if (isTreeEmpty()) {
if (placeholderRegion == null) {
placeholderRegion = new StackPane();
placeholderRegion.getStyleClass().setAll("placeholder");
getChildren().add(placeholderRegion);
placeholderLabel = new Label("No treeItems");
placeholderRegion.getChildren().setAll(placeholderLabel);
}
}
getVirtualFlow().setVisible(!isTreeEmpty());
if (placeholderRegion != null)
placeholderRegion.setVisible(isTreeEmpty());
}
@Override
protected void layoutChildren(double x, double y, double w, double h) {
super.layoutChildren(x, y, w, h);
if (placeholderRegion != null && placeholderRegion.isVisible()) {
placeholderRegion.resizeRelocate(x, y, w, h);
}
}
private boolean isTreeEmpty() {
return getSkinnable().getRoot() == null;
}
}
private Parent createContent() {
TreeView<String> tree = new TreeView<>() {
@Override
protected Skin<?> createDefaultSkin() {
return new TreeViewPlaceholderSkin<>(this);
}
};
Button toggle = new Button("toggleRoot");
toggle.setOnAction(e -> {
TreeItem<String> root = tree.getRoot();
tree.setRoot(root == null ? new TreeItem<>("root") : null);
});
BorderPane content = new BorderPane(tree);
content.setBottom(toggle);
return content;
}
@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
//stage.setTitle(FXUtils.version());
stage.show();
}
public static void main(String[] args) {
launch(args);
}
@SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(TreeViewWithPlaceholder.class.getName());
}