Java 树视图的占位符?

Java 树视图的占位符?,java,listview,javafx,treeview,Java,Listview,Javafx,Treeview,我有一个树视图,它在开始时是空的,我想设置一个占位符,直到它是空的。与ListView(setPlaceholder())可用的类似 我的第一个想法是将TreeView包装成一个边框窗格,然后根据TreeView中的元素数量更改中心。问题是,我通过拖放将元素添加到树视图中,如果我将标签设置到中心以替换占位符,我将无法再在树视图中拖放我的项目。任何建议都将不胜感激。TreeView没有占位符支持-不完全确定,为什么不确定,但可能是一棵空树(不管这意味着什么:空根?没有孩子的根?根不显示?)是一种稀

我有一个树视图,它在开始时是空的,我想设置一个占位符,直到它是空的。与ListView(setPlaceholder())可用的类似


我的第一个想法是将TreeView包装成一个边框窗格,然后根据TreeView中的元素数量更改中心。问题是,我通过拖放将元素添加到树视图中,如果我将标签设置到中心以替换占位符,我将无法再在树视图中拖放我的项目。任何建议都将不胜感激。

TreeView没有占位符支持-不完全确定,为什么不确定,但可能是一棵空树(不管这意味着什么:空根?没有孩子的根?根不显示?)是一种稀有物种

不过,通过遵循支持它的虚拟化控件f.i.TableView的实现,实现起来相当简单。我们所需要的只是一张定制的树皮

  • 管理(根据需要创建并添加到树的层次结构和布局)占位符
  • 侦听树的相关状态,并根据需要更新占位符的可见性
例如,通过按钮将树的根在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());

}
公共类TreeViewWithPlaceholder扩展应用程序{
私有静态类TreeViewPlaceholderSkin扩展了TreeViewSkin{
私有区域;
自有品牌;
公共树视图PlaceHolderSkin(树视图控制){
超级(控制);
installPlaceholderSupport();
}
私有void installplaceholder支持(){
registerChangeListener(getSkinnable().rootProperty(),e->updatePlaceholderSupport());
updatePlaceholderSupport();
}
/**
*根据树是否更新占位符/流可见性
*被认为是空的。
* 
*基本上是从TableViewSkinBase复制的。
*/
私有void updatePlaceholderSupport(){
if(isTreeEmpty()){
if(占位符区域==null){
占位符区域=新的StackPane();
占位符区域.getStyleClass().setAll(“占位符”);
getChildren().add(占位符区域);
占位符标签=新标签(“无树项”);
placeholderRegion.getChildren().setAll(占位符标签);
}
}
getVirtualFlow().setVisible(!isTreeEmpty());
if(占位符区域!=null)
placeholderRegion.setVisible(isTreeEmpty());
}
@凌驾
受保护的无效布局子项(双x、双y、双w、双h){
超级布局(x,y,w,h);
if(placeholderRegion!=null&&placeholderRegion.isVisible()){
占位符区域。重设为长形(x,y,w,h);
}
}
私有布尔值isTreeEmpty(){
返回getSkinnable().getRoot()==null;
}
}
私有父createContent(){
TreeView树=新的TreeView(){
@凌驾
受保护的皮肤createDefaultSkin(){
返回新的TreeViewPlaceholderSkin(此);
}
};
按钮切换=新按钮(“切换根”);
切换设置动作(e->{
TreeItem root=tree.getRoot();
tree.setRoot(root==null?新TreeItem(“root”):null);
});
边框窗格内容=新边框窗格(树);
content.setBottom(切换);
返回内容;
}
@凌驾
public void start(Stage)引发异常{
stage.setScene(新场景(createContent());
//stage.setTitle(FXUtils.version());
stage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
@抑制警告(“未使用”)
专用静态最终记录器日志=记录器
.getLogger(TreeViewWithPlaceholder.class.getName());
}

TreeView没有占位符支持-不完全确定,为什么不确定,但可能是一个空树(不管这意味着什么:空根?根没有子项?根没有显示?)是一个罕见的物种

不过,通过遵循支持它的虚拟化控件f.i.TableView的实现,实现起来相当简单。我们所需要的只是一张定制的树皮

  • 管理(根据需要创建并添加到树的层次结构和布局)占位符
  • 侦听树的相关状态,并根据需要更新占位符的可见性
例如,通过按钮将树的根在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());

}
公共类TreeViewWithPlaceholder扩展应用程序{
私有静态类TreeViewPlaceholderSkin扩展了TreeViewSkin{
私有区域;
自有品牌;
公共树视图PlaceHolderSkin(树视图控制){
超级(控制);
installPlaceholderSupport();
}
私有void installplaceholder支持(){
registerChangeListener(getSkinnable().rootProperty(),e->updatePlaceholderSupport());
updatePlaceholderSupport();
}
/**
*根据树是否更新占位符/流可见性
*被认为是空的。
* 
*基本上是从TableViewSkinBase复制的。
*/
私有void updatePlaceholderSupport(){
if(isTreeEmpty()){
if(占位符区域==null){
占位符区域=新的StackPane();
占位符区域.getStyleClass().setAll(“占位符”);
getChildren().add(占位符区域);
占位符标签=新标签(“无树项”);
占位符区域