JavaFX TreeTableView leaves icons behind when collapsing

僤鯓⒐⒋嵵緔 提交于 2019-12-06 05:48:45

问题


I have a TreeTableView where every node has an icon. Everything works perfectly when I expand the tree, but when I collapse the tree, the icons of the no longer visible items are left behind.

The rows and the text are removed, but the icons remain "free-floating". In the screenshot you can see the TreeTableView twice, once expanded with the correct text, and once collapsed with only the remaining icons.

The screenshot above was created from the following minimal example (you just need to add your own icon.png):

import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableColumn.CellDataFeatures;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableView;
import javafx.stage.Stage;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

public class TreeTableViewSample extends Application {
    private static final Image icon = new Image(TreeTableViewSample.class.getResourceAsStream("icon.png"));

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) {
        stage.setTitle("Tree Table View Samples");
        final Scene scene = new Scene(new Group(), 200, 400);
        Group sceneRoot = (Group)scene.getRoot();  

        //Creating tree items
        final TreeItem<String> childNode1 = new TreeItem<>("Child Node 1", new ImageView(icon));
        final TreeItem<String> childNode2 = new TreeItem<>("Child Node 2", new ImageView(icon));
        final TreeItem<String> childNode3 = new TreeItem<>("Child Node 3", new ImageView(icon));

        //Creating the root element
        final TreeItem<String> root = new TreeItem<>("Root node", new ImageView(icon));
        root.setExpanded(true);   

        //Adding tree items to the root
        root.getChildren().setAll(childNode1, childNode2, childNode3);        

        //Creating a column
        TreeTableColumn<String,String> column = new TreeTableColumn<>("Column");
        column.setPrefWidth(150);   

        //Defining cell content
        column.setCellValueFactory((CellDataFeatures<String, String> p) -> 
            new ReadOnlyStringWrapper(p.getValue().getValue()));  

        //Creating a tree table view
        final TreeTableView<String> treeTableView = new TreeTableView<>(root);
        treeTableView.getColumns().add(column);
        treeTableView.setPrefWidth(152);
        treeTableView.setShowRoot(true);             
        sceneRoot.getChildren().add(treeTableView);
        stage.setScene(scene);
        stage.show();
    }     
}

I have tried this using OpenJDK and Oracle Java 8u92 on Linux and using Oracle Java 8u92 on Windows.


回答1:


That's a bug. It works fine with my old 1.8.0_71 but fails as you describe with 1.8.0_92.

IMHO, defining a graphic in the TreeItem is nonsense anyway: the TreeItem is part of the model for the tree and should contain data only, not details of how the data are presented. The graphic should be a property of the cell and should be defined in a cell factory. The following workaround works as expected:

import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableColumn.CellDataFeatures;
import javafx.scene.control.TreeTableView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class TreeTableViewSample extends Application {
    private static final Image icon = new Rectangle(12, 12, Color.CORNFLOWERBLUE).snapshot(null, null);

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) {
        stage.setTitle("Tree Table View Samples");
        final Scene scene = new Scene(new Group(), 200, 400);
        Group sceneRoot = (Group)scene.getRoot();  

        //Creating tree items
//        final TreeItem<String> childNode1 = new TreeItem<>("Child Node 1", new ImageView(icon));
//        final TreeItem<String> childNode2 = new TreeItem<>("Child Node 2", new ImageView(icon));
//        final TreeItem<String> childNode3 = new TreeItem<>("Child Node 3", new ImageView(icon));

        final TreeItem<String> childNode1 = new TreeItem<>("Child Node 1");
        final TreeItem<String> childNode2 = new TreeItem<>("Child Node 2");
        final TreeItem<String> childNode3 = new TreeItem<>("Child Node 3");

        //Creating the root element
//        final TreeItem<String> root = new TreeItem<>("Root node", new ImageView(icon));
        final TreeItem<String> root = new TreeItem<>("Root node");
        root.setExpanded(true);   

        //Adding tree items to the root
        root.getChildren().setAll(childNode1, childNode2, childNode3);        

        //Creating a column
        TreeTableColumn<String,String> column = new TreeTableColumn<>("Column");
        column.setPrefWidth(150);   

        //Defining cell content
        column.setCellValueFactory((CellDataFeatures<String, String> p) -> 
            new ReadOnlyStringWrapper(p.getValue().getValue()));  


        // cell factory to display graphic:
        column.setCellFactory(ttc -> new TreeTableCell<String, String>() {

            private final ImageView graphic = new ImageView(icon);

            @Override
            protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                setText(empty ? null : item);
                setGraphic(empty ? null : graphic);
            }
        });

        //Creating a tree table view
        final TreeTableView<String> treeTableView = new TreeTableView<>(root);
        treeTableView.getColumns().add(column);
        treeTableView.setPrefWidth(152);
        treeTableView.setShowRoot(true);             
        sceneRoot.getChildren().add(treeTableView);
        stage.setScene(scene);
        stage.show();
    }     
}


来源:https://stackoverflow.com/questions/36917220/javafx-treetableview-leaves-icons-behind-when-collapsing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!