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

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

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

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


person witchi    schedule 04.12.2015    source источник


Ответы (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 и которому требуется это изображение.

person Uluk Biy    schedule 04.12.2015
comment
Я думаю, это изображение не находится в той же вертикальной координате, что и изображения раскрытия. Изображение должно быть перед (слева) графическими и текстовыми элементами. Я протестировал псевдокласс для переключения фонового изображения узла раскрытия в CSS, но он не работает. - person witchi; 05.12.2015

Я определил структуру 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» в обоих случаях (не / расширенный).

person witchi    schedule 09.12.2015
comment
будьте осторожны: теперь у вас есть несогласованное состояние как leafProperty.get ()! = isLeaf () - даже если вы находитесь в хорошей / плохой компании с примером мотивирующего документа в TreeItem, это ошибка в вашем коде (а также в документе / доступность leafItem bugs.openjdk.java.net/browse/JDK-8089811 ). Это может сойти вам с рук, но стоит отметить это как таковое. - person kleopatra; 10.12.2015