javafx - JavaFX 树的上下文菜单

标签 javafx javafx-2 javafx-8

我想为 JavaFX 创建上下文菜单。这是我测试过的代码。但是由于某种原因,当我右键单击树节点时没有上下文菜单。你能帮我找出我的错误吗。

import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.ContextMenuBuilder;
import javafx.scene.control.MenuItemBuilder;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;

public class MainApp extends Application
{
    List<Employee> employees = Arrays.<Employee>asList(
        new Employee("New Chassi", "New Datacenter"),
        new Employee("New Battery", "New Rack"),
        new Employee("New Chassi", "New Server"),
        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"),
        new Employee("Jacob Smith", "Accounts Department"),
        new Employee("Isabella Johnson", "Accounts Department"));
    TreeItem<String> rootNode = new TreeItem<>("MyCompany Human Resources");

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

    TreeView<String> treeView = new TreeView<>(rootNode);

    @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<String> depNode = new TreeItem<>(
                    employee.getDepartment()//,new ImageView(depIcon)   // Set picture
                );
                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.setCellFactory(new Callback<TreeView<String>, TreeCell<String>>()
        {

            @Override
            public TreeCell<String> call(TreeView<String> arg0)
            {
                // custom tree cell that defines a context menu for the root tree item
                return new MyTreeCell();
            }
        });

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

    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);
        }
    }

    class MyTreeCell extends TextFieldTreeCell<String>
    {
        private ContextMenu rootContextMenu;

        public MyTreeCell()
        {
            // instantiate the root context menu
            rootContextMenu
                = ContextMenuBuilder.create()
                .items(
                    MenuItemBuilder.create()
                    .text("Menu Item")
                    .onAction(
                        new EventHandler<ActionEvent>()
                        {
                            @Override
                            public void handle(ActionEvent arg0)
                            {
                                System.out.println("Menu Item Clicked!");
                            }
                        }
                    )
                    .build()
                )
                .build();
        }

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

            // if the item is not empty and is a root...
            if (!empty && getTreeItem().getParent() == null)
            {
                setContextMenu(rootContextMenu);
            }
        }
    }

}

最佳答案

您应该将上下文菜单分配给 TreeView,而不是将其分配给单元工厂。这是上下文菜单工作的代码:

import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.ContextMenuBuilder;
import javafx.scene.control.MenuItemBuilder;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;

public class Test extends Application
{
    List<Employee> employees = Arrays.<Employee>asList(
        new Employee("New Chassi", "New Datacenter"),
        new Employee("New Battery", "New Rack"),
        new Employee("New Chassi", "New Server"),
        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"),
        new Employee("Jacob Smith", "Accounts Department"),
        new Employee("Isabella Johnson", "Accounts Department"));
    TreeItem<String> rootNode = new TreeItem<>("MyCompany Human Resources");

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

    TreeView<String> treeView = new TreeView<>(rootNode);

    @Override
    public void start(Stage stage)
    {

        // instantiate the root context menu
        ContextMenu rootContextMenu
            = ContextMenuBuilder.create()
            .items(
                MenuItemBuilder.create()
                .text("Menu Item")
                .onAction(
                    new EventHandler<ActionEvent>()
                    {
                        @Override
                        public void handle(ActionEvent arg0)
                        {
                            System.out.println("Menu Item Clicked!");
                        }
                    }
                )
                .build()
            )
            .build();

        treeView.setContextMenu(rootContextMenu);

        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<String> depNode = new TreeItem<>(
                    employee.getDepartment()//,new ImageView(depIcon)   // Set picture
                );
                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);


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

    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);
        }
    }


}

关于javafx - JavaFX 树的上下文菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21957553/

相关文章:

JAVAFX:从数据库加载图像

3d - JavaFX 3D 对象之间的并集、交集和差异

java - 如何确保用户只允许输入整数?

java - 如何在 JavaFX 中将鼠标和事件处理程序组合在一起?

JavaFX 按钮悬停缩放

java - StageStyle.TRANSPARENT 的表现

java - JavaFX 中纯粹悬停时触发的菜单?

java - 奇怪的 TableView.itemsProperty 行为?

javafx - 如何在调整 ScrollPane 大小时显示滚动条? (在 JavaFX 中)

java - xAxis 条形图中同一位置的所有标签 - JavaFx