Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8093829

TreeView Erroneous ContextMenus shown

XMLWordPrintable

      I have an application using a TreeView with contextMenus working in Jd7u25. I migrate in Jdk8u5 and contextMenus do not work anymore. I think the wrong TreeCell is used to open the popup menu.

      To see the problem, you can just launch the TreeViewSample provided by the documentation. The popupMenu "Add Employee" shall not appear on leaf items (if ( !getTreeItem().isLeaf()&&getTreeItem().getParent()!= null) setContextMenu(addMenu);) but it does on employees cell like "Jacob Smith" for example.

      The code to test :
      public class TreeViewSample extends Application {
        
        private final Node rootIcon =
            new ImageView(new Image(getClass().getResourceAsStream("/16x16-table.png")));
        private final Image depIcon =
            new Image(getClass().getResourceAsStream("/16x16-chartbar.png"));
        List<Employee> employees = Arrays.<Employee>asList(
                new Employee("Jacob Smith", "Accounts Department"),
                new Employee("Isabella Johnson", "Accounts Department"),
                new Employee("Ethan Williams", "Sales Department"),
                new Employee("Emma Jones", "Sales Department"),
                new Employee("Michael Brown", "Sales Department"),
                new Employee("Anna Black", "Sales Department"),
                new Employee("Rodger York", "Sales Department"),
                new Employee("Susan Collins", "Sales Department"),
                new Employee("Mike Graham", "IT Support"),
                new Employee("Judy Mayer", "IT Support"),
                new Employee("Gregory Smith", "IT Support"));
        TreeItem<String> rootNode =
            new TreeItem<>("MyCompany Human Resources", rootIcon);

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

        @Override
        public void start(Stage stage) {
            rootNode.setExpanded(true);
            for (Employee employee : employees) {
                TreeItem<String> empLeaf = new TreeItem<>(employee.getName());
                boolean found = false;
                for (TreeItem<String> depNode : rootNode.getChildren()) {
                    if (depNode.getValue().contentEquals(employee.getDepartment())){
                        depNode.getChildren().add(empLeaf);
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    TreeItem depNode = new TreeItem(employee.getDepartment(),
                        new ImageView(depIcon)
                    );
                    rootNode.getChildren().add(depNode);
                    depNode.getChildren().add(empLeaf);
                }
            }

            stage.setTitle("Tree View Sample");
            VBox box = new VBox();
            final Scene scene = new Scene(box, 400, 300);
            scene.setFill(Color.LIGHTGRAY);

            TreeView<String> treeView = new TreeView<>(rootNode);
            treeView.setEditable(true);
            treeView.setCellFactory((TreeView<String> p) ->
                new TextFieldTreeCellImpl());

            box.getChildren().add(treeView);
            stage.setScene(scene);
            stage.show();
        }

        private final class TextFieldTreeCellImpl extends TreeCell<String> {

            private TextField textField;
            private final ContextMenu addMenu = new ContextMenu();

            public TextFieldTreeCellImpl() {
                MenuItem addMenuItem = new MenuItem("Add Employee");
                addMenu.getItems().add(addMenuItem);
                addMenuItem.setOnAction((ActionEvent t) -> {
                    TreeItem newEmployee =
                        new TreeItem<>("New Employee");
                    getTreeItem().getChildren().add(newEmployee);
                });
            }

            @Override
            public void startEdit() {
                super.startEdit();

                if (textField == null) {
                    createTextField();
                }
                setText(null);
                setGraphic(textField);
                textField.selectAll();
            }

            @Override
            public void cancelEdit() {
                super.cancelEdit();

                setText((String) getItem());
                setGraphic(getTreeItem().getGraphic());
            }

            @Override
            public void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);

                if (empty) {
                    setText(null);
                    setGraphic(null);
                } else {
                    if (isEditing()) {
                        if (textField != null) {
                            textField.setText(getString());
                        }
                        setText(null);
                        setGraphic(textField);
                    } else {
                        setText(getString());
                        setGraphic(getTreeItem().getGraphic());
                        if (
                            !getTreeItem().isLeaf()&&getTreeItem().getParent()!= null
                        ){
                            setContextMenu(addMenu);
                        }
                    }
                }
            }
            
            private void createTextField() {
                textField = new TextField(getString());
                textField.setOnKeyReleased((KeyEvent t) -> {
                    if (t.getCode() == KeyCode.ENTER) {
                        commitEdit(textField.getText());
                    } else if (t.getCode() == KeyCode.ESCAPE) {
                        cancelEdit();
                    }
                });
                
            }

            private String getString() {
                return getItem() == null ? "" : getItem().toString();
            }
        }

        public static class Employee {

            private final SimpleStringProperty name;
            private final SimpleStringProperty department;

            private Employee(String name, String department) {
                this.name = new SimpleStringProperty(name);
                this.department = new SimpleStringProperty(department);
            }

            public String getName() {
                return name.get();
            }

            public void setName(String fName) {
                name.set(fName);
            }

            public String getDepartment() {
                return department.get();
            }

            public void setDepartment(String fName) {
                department.set(fName);
            }
        }
      }

            jgiles Jonathan Giles
            duke J. Duke
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: