JavaFX树的上下文菜单

JavaFX树的上下文菜单,javafx,javafx-2,javafx-8,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.

我想为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);
            }
        }
    }

}
导入java.util.array;
导入java.util.List;
导入javafx.application.application;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.event.ActionEvent;
导入javafx.event.EventHandler;
导入javafx.scene.scene;
导入javafx.scene.control.ContextMenu;
导入javafx.scene.control.ContextMenuBuilder;
导入javafx.scene.control.MenuItemBuilder;
导入javafx.scene.control.TreeCell;
导入javafx.scene.control.TreeItem;
导入javafx.scene.control.TreeView;
导入javafx.scene.control.cell.TextFieldTreeCell;
导入javafx.scene.layout.VBox;
导入javafx.scene.paint.Color;
导入javafx.stage.stage;
导入javafx.util.Callback;
公共类MainApp扩展应用程序
{
List employees=Arrays.asList(
新员工(“新Chassi”、“新数据中心”),
新员工(“新电池”、“新机架”),
新员工(“新Chassi”、“新服务器”),
新员工(“安娜·布莱克”、“销售部”),
新员工(“Rodger York”、“销售部”),
新员工(“Susan Collins”,“销售部”),
新员工(“Mike Graham”、“IT支持”),
新员工(“Judy Mayer”、“IT支持”),
新员工(“Gregory Smith”、“IT支持”),
新员工(“Jacob Smith”,“会计部”),
新员工(“伊莎贝拉·约翰逊”,“会计部”);
TreeItem rootNode=新的TreeItem(“MyCompany人力资源”);
公共静态void main(字符串[]args)
{
应用程序启动(args);
}
TreeView TreeView=新的TreeView(rootNode);
@凌驾
公众假期开始(阶段)
{
setExpanded(true);
用于(员工:员工)
{
TreeItem empLeaf=newtreeitem(employee.getName());
布尔值=false;
for(TreeItem depNode:rootNode.getChildren())
{
if(depNode.getValue().contentEquals(employee.getDepartment()))
{
depNode.getChildren().add(empLeaf);
发现=真;
打破
}
}
如果(!找到)
{
TreeItem depNode=新TreeItem(
employee.getDepartment()//,新建图像视图(depIcon)//设置图片
);
rootNode.getChildren().add(depNode);
depNode.getChildren().add(empLeaf);
}
}
stage.setTitle(“树视图示例”);
VBox box=新的VBox();
最终场景=新场景(框,400,300);
场景。设置填充(颜色。浅灰色);
setCellFactory(新回调()
{
@凌驾
公共TreeCell调用(TreeView arg0)
{
//自定义树单元,用于定义根树项的上下文菜单
返回新的MyTreeCell();
}
});
box.getChildren().add(treeView);
舞台场景;
stage.show();
}
公共静态类雇员
{
私有最终SimpleStringProperty名称;
私人物业署;
私人员工(字符串名称、字符串部门)
{
this.name=新的SimpleStringProperty(名称);
this.department=新SimpleStringProperty(部门);
}
公共字符串getName()
{
返回name.get();
}
public void setName(字符串fName)
{
name.set(fName);
}
公共部门()
{
返回部门。get();
}
公共部门(字符串fName)
{
部门设置(fName);
}
}
类MyTreeCell扩展了TextFieldTreeCell
{
私有上下文菜单根上下文菜单;
公共MyTreeCell()
{
//实例化根上下文菜单
根上下文菜单
=ContextMenuBuilder.create()
.项目(
MenuItemBuilder.create()
.text(“菜单项”)
.行动(
新的EventHandler()
{
@凌驾
公共无效句柄(ActionEvent arg0)
{
System.out.println(“单击菜单项!”);
}
}
)
.build()
)
.build();
}
@凌驾
public void updateItem(字符串项,布尔值为空)
{
super.updateItem(项,空);
//如果项目不是空的并且是根目录。。。
如果(!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);
        }
    }


}
导入java.util.array;
导入java.util.List;
导入javafx.application.application;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.event.ActionEvent;
导入javafx.event.EventHandler;
导入javafx.scene.scene;
导入javafx.scene.control.ContextMenu;
导入javafx.scene.control.ContextMenuBuilder;
导入javafx.scene.control.MenuItemBuilder;
导入javafx.scene.control.TreeCell;
导入javafx.scene.control.TreeItem;
导入javafx.scene.control.TreeView;
导入javafx.scene.control.cell.TextFieldTreeCell;
导入javafx.scene.layout.VBox;
导入javafx.scene.paint.Color;
导入javafx.stage.stage;
导入javafx.util.Callback;
公共类测试扩展了应用程序
{
雇员名单
MenuItem entry1 = new MenuItem("Test with Icon", graphicNode);
entry1.setOnAction(ae -> ...);
MenuItem entry2 = new MenuItem("Test without Icon");
entry2.setOnAction(ae -> ...);

myTreeView.setContextMenu(new ContextMenu(entry1, entry2));
//The "" is important, without it the tree item would not appear at all
TreeItem<String> childItem = new TreeItem<>("");  

//Create a label with the string you would use for the tree item
childItem.setGraphic(new Label("TreeItem Label"));

//Add menu items for contextMenu
ContextMenu contextMenu = new ContextMenu();

childItem.getGraphic().setOnContextMenuRequested(e -> {
    //Sets the context menu for the label.
    contextMenu.show(childItem.getGraphic(), e.getScreenX(), e.getScreenY()));  
}
package javaapplication2;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.stage.Stage;
import javafx.util.Callback;


public class JavaApplication2 extends Application {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}

@Override
public void start(Stage stage) throws Exception {
    //Start a new TreeView
    TreeView<String> tv = new TreeView<>(new TreeItem<>("Root"));

    //Set the cell factory
    tv.setCellFactory(new Callback() {
        @Override
        public Object call(Object p) {
            return new TreeCellWithMenu();
        }
    });

    //Fill tree with some things
    tv.getRoot().getChildren().add(new TreeItem<>("1"));
    tv.getRoot().getChildren().add(new TreeItem<>("2"));
    tv.getRoot().getChildren().add(new TreeItem<>("3"));

    //Stage a new scene
    stage.setScene(new Scene(tv));

    //Show the stage
    stage.show();
}

public class TreeCellWithMenu extends TextFieldTreeCell<String> {

    ContextMenu men;

    public TreeCellWithMenu() {
        //ContextMenu with one entry
        men = new ContextMenu(new MenuItem("Right Click"));
    }

    @Override
    public void updateItem(String t, boolean bln) {
        //Call the super class so everything works as before
        super.updateItem(t, bln);
        //Check to show the context menu for this TreeItem
        if (showMenu(t, bln)) {
            setContextMenu(men);
        }else{
            //If no menu for this TreeItem is used, deactivate the menu
            setContextMenu(null);
        }
    }
    
    //Deccide if a menu should be shown or not
    private boolean showMenu(String t, boolean bln){
        if (t != null && !t.equals("Root")) {
            return true;
        }
        return false;
    }        

}

}