java - TreeView 展开/折叠奇怪的行为

标签 java css javafx treeview treecell

我建模了 TreeView<Playlist>这样,具有子节点的节点就有一个图形文件夹图标,而其他节点则有一个播放列表图标。样式几乎可以工作,但是当展开/折叠节点时,图形图标会损坏。

当单击节点时,它始终显示正确的样式,但是当展开/折叠或添加新节点时,TreeView像这样操作:

treeview-strange-behaviour

这是定义 TreeCell 的代码的一部分在 TreeView

public class PlaylistTreeView extends TreeView<Playlist> {

    public PlaylistTreeView() {
    ...

    setShowRoot(false);
    setCellFactory(treeView -> new PlaylistTreeCell());

    ...
    }

    private class PlaylistTreeCell extends TreeCell<Playlist> {

        @Override
        public void updateItem(Playlist p, boolean empty) {
            super.updateItem(p, empty);
            if(p == null || empty) {
                textProperty().unbind();
                setText("");
                setGraphic(null);
            }
            else {
                if(p.isFolder())
                    setId("playlist-folder-tree-cell");
                else
                    setId("playlist-tree-cell");
                textProperty().bind(p.nameProperty());
            }
        }
    }
}

这些是影响这些组件的唯一样式 css :

.tree-cell, .list-cell {
    -fx-background-color: rgb(243, 243, 243);
}

#playlist-tree-cell {
    -fx-graphic: url('../icons/playlist-black-icon.png');
}

#playlist-tree-cell:selected {
    -fx-graphic: url('../icons/playlist-white-icon.png');
}

#playlist-folder-tree-cell {
    -fx-graphic: url('../icons/playlist-folder-black-icon.png');    
}

#playlist-folder-tree-cell:selected {
    -fx-graphic: url('../icons/playlist-folder-white-icon.png');
}

.list-cell:selected, .tree-cell:selected {  
    -fx-background-color: black;
    -fx-text-fill: white;
}

我在这里缺少什么?

最佳答案

我使用CSS伪类解决了这个问题。

public class PlaylistTreeView extends TreeView<Playlist> {

    private PseudoClass playlist = PseudoClass.getPseudoClass("playlist");
    private PseudoClass playlistSelected = PseudoClass.getPseudoClass("playlist-selected");
    private PseudoClass folder = PseudoClass.getPseudoClass("folder");
    private PseudoClass folderSelected = PseudoClass.getPseudoClass("folder-selected");

    public PlaylistTreeView() {
        setShowRoot(false);
        setCellFactory(treeView -> new PlaylistTreeCell());
    }

    private class PlaylistTreeCell extends TreeCell<Playlist> {

        public PlaylistTreeCell() {
            super();

            ChangeListener<Boolean> isFolderListener = (obs, oldPlaylist, newPlaylist) -> {
                boolean isFolder = newPlaylist.booleanValue();
                boolean isSelected = selectedProperty().get();
                updatePseudoClassesStates(isFolder, isSelected);
            };

            ChangeListener<Boolean> isSelectedListener = (obs, oldValue, newValue) -> {
                boolean isFolder = itemProperty().getValue().isFolder();
                boolean isSelected = newValue.booleanValue();
                updatePseudoClassesStates(isFolder, isSelected);
            };

            itemProperty().addListener((obs, oldPlaylist, newPlaylist) -> {

                if(oldPlaylist != null) {
                    textProperty().unbind();
                    setText("");
                    oldPlaylist.folderProperty().removeListener(isFolderListener);
                    selectedProperty().removeListener(isSelectedListener);
                }

                if(newPlaylist != null) {
                    textProperty().bind(newPlaylist.nameProperty());
                    newPlaylist.folderProperty().addListener(isFolderListener);
                    selectedProperty().addListener(isSelectedListener);

                    updatePseudoClassesStates(newPlaylist.isFolder(), selectedProperty().get());
                }
                else {
                    pseudoClassStateChanged(folder, false);
                    pseudoClassStateChanged(folderSelected, false);
                    pseudoClassStateChanged(playlist, false);
                    pseudoClassStateChanged(playlistSelected, false);
                }
            });
        }

        private void updatePseudoClassesStates(boolean isFolder, boolean isSelected) {
            pseudoClassStateChanged(folder, isFolder && !isSelected);
            pseudoClassStateChanged(folderSelected, isFolder && isSelected);
            pseudoClassStateChanged(playlist, !isFolder && !isSelected);
            pseudoClassStateChanged(playlistSelected, !isFolder && isSelected);
        }
}

style.css 文件:

.tree-cell, .list-cell {
    -fx-background-color: rgb(243, 243, 243);
}

.tree-cell:empty {
    -fx-graphic: none;
}

.tree-cell:playlist {
    -fx-graphic: url('../playlist-black-icon.png');
}

.tree-cell:playlist-selected {
    -fx-graphic: url('../playlist-white-icon.png');
}

.tree-cell:folder {
    -fx-graphic: url('../playlist-folder-black-icon.png');
}

.tree-cell:folder-selected {
    -fx-graphic: url('../playlist-folder-white-icon.png');
}

.tree-cell:playlist-selected, .tree-cell:folder-selected {
    -fx-background-color: black;
    -fx-text-fill: white;
}

enter image description here

关于java - TreeView 展开/折叠奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37472368/

相关文章:

java - 将 HTML 字符串传递给 jQuery 函数

html - Css 渐变边框颜色

HTML垂直滚动条只有当水平滚动条在右边时才可见

java - 是否可以将包含自定义 JavaFX 控件的 JAR 导入到 Scene Builder 中?

java - 使用 HashMap 和 List 进行嵌套双括号初始化

java - Magical Number 的省时递归

java - Webview JavaFX 与进程一起运行

java - 如何在Java中将图像转换为形状?

java - 耗尽结果集

javascript - 更改列表后更改类