JavaFX8: отобразить изображение как узел раскрытия для бездетных TreeViewItems

Я определил изображения для двух состояний узла раскрытия (свернуть / развернуть) в соответствии с изменением развернуть и свернуть изображение TreeView JavaFX 2.2

Но я хотел бы иметь третье изображение для узлов папок, у которых до сих пор нет дочерних узлов. Не должно быть возможности развернуть / свернуть такие узлы, но также должно отображаться изображение (например, minus.png для развернутых узлов, plus.png для свернутых узлов и пустой прямоугольник для узлов папок без дочерних узлов).

Является ли это возможным?

2 ответа

Отсутствие потомков означает, что элемент дерева является листовым узлом с типом "папка". Вы можете использовать графическое свойство элемента дерева, чтобы показать изображение "пустой прямоугольник":

ImageView ivfolder = new ImageView( "path/to/empty_rectangle.png" );

// You may use bindings
treeitem.graphicProperty().bind( Bindings
   .when( treeitem.leafProperty() )
   .then( ivfolder )
   .otherwise( ( ImageView ) null ) 
);

// or set explicitly for that tree item
TreeItem<Folder> item = new TreeItem<>( "<empty>", ivfolder );

Не забудьте создать новые изображения для каждого элемента дерева, добавленного в TreeView и нуждающегося в этом изображении.

Я определил структуру CSS для бездетного случая:

.tree-cell:browser-folder-childless .tree-disclosure-node .arrow {
     -fx-font-weight: bold;
     -fx-shape: null;
     -fx-background-color: null;
     -fx-background-image: url("childless.png");
     -fx-background-repeat:  no-repeat;
}

.tree-cell:browser-folder-childless:expanded .tree-disclosure-node .arrow {
    -fx-font-weight: bold;
    -fx-shape: null;
    -fx-background-color: null;
    -fx-background-image: url("childless.png");
    -fx-background-repeat:  no-repeat;
}

Далее я расширил класс TreeItem:

public class BrowserTreeItem extends TreeItem<MyData> {

    public BrowserTreeItem(MyData data) {
        super(data);
    }

    @Override
    public boolean isLeaf() {
        return (getValue().getTypes().contains(NodeType.FOLDER) && getValue().getChildren().size() == 0) ? false : super.isLeaf();
    }
}

Таким образом, TreeItem всегда возвращает false для isLeaf () в случае бездетной папки. Метод isLeaf () будет использоваться com.sun.javafx.scene.control.skin.TreeCellSkin.class, чтобы решить, следует ли удалять узел раскрытия. Перестройка узла может быть сложной задачей, поэтому я предотвращаю удаление узла.

Это приводит к нормальному раскрытию узла, теперь я должен изменить изображение узла.

Было бы неплохо перезаписать также метод isExanded () класса TreeItem. Тогда мне понадобится только одна структура CSS (метод всегда возвращает false для бездетных папок). Но isExpanded () является окончательным. Поэтому я не могу предотвратить переключение не / расширенного пользователем, и мне нужно определить две структуры CSS.

Затем я построил TreeCellFactory, которая генерирует мои собственные классы BrowserTreeCell. Он переключает состояние PseudoClass, которое мы используем в CSS выше, чтобы активировать некоторые новые изображения для узла раскрытия.

public class BrowserTreeCell extends TreeCell<MyData> {

    private final PseudoClass childless = PseudoClass.getPseudoClass("browser-folder-childless");

    @Override
    protected void updateItem(MyData item, boolean empty) {
        super.updateItem(item, empty);

        if (!empty && item != null) {

            setText(item.getName());
            setGraphic(item.getThumbnail());
            setTooltip(item.getTooltip());

        } else {

            setText("");
            setGraphic(null);
            setTooltip(null);
        }

        pseudoClassStateChanged(childless, !empty && item != null && item.getTypes().contains(NodeType.FOLDER) && item.getChildren().size() == 0);

    }
}

В результате я получаю узел раскрытия с "childless.png" в обоих случаях (не расширен).

Другие вопросы по тегам