如何在javaFX中使上下文菜单在树视图上工作?

如何在javaFX中使上下文菜单在树视图上工作?,java,javafx,treeview,contextmenu,Java,Javafx,Treeview,Contextmenu,我想要一个树状视图项目的上下文菜单。 我希望事件处理程序的ActionEvent会提供有关单击哪个TreeView项的信息,但我发现getSource和getTarget返回一个菜单项。我如何才能找到已单击的TreeView项目?我可以在单独的选项卡中有多个TreeView FileContextMenu cm = new FileContextMenu(new EventHandler<ActionEvent>() { public void handle(

我想要一个树状视图项目的上下文菜单。 我希望事件处理程序的ActionEvent会提供有关单击哪个TreeView项的信息,但我发现getSource和getTarget返回一个菜单项。我如何才能找到已单击的TreeView项目?我可以在单独的选项卡中有多个TreeView

    FileContextMenu cm = new FileContextMenu(new EventHandler<ActionEvent>() {
        public void handle(ActionEvent e) {
            System.out.println("Open File");
            //MenuItem mi = (MenuItem)e.getSource();
            EventTarget et = e.getTarget();
            //File editorFile = new File(mi.getId());
            System.out.println(et);
            //mainWindowController.openEditor(editorFile);
        }
    }, new EventHandler<ActionEvent>() {
        public void handle(ActionEvent e) {
            System.out.println("Create Project From Template");
        }
    });
我现在尝试使用cellfactory,但我不知道如何使用p参数来查找单元格值。我的代码是:

this.fileTreeView.setCellFactory(new Callback<TreeView<FileShort>,TreeCell<FileShort>>(){
    @Override
    public TreeCell<FileShort> call(TreeView<FileShort> p) {
        TreeCell<FileShort> cell = new TreeCell<FileShort>();
        cell.setContextMenu(cm);
        return cell;
    }
});
this.fileTreeView.setCellFactory(新回调(){
@凌驾
公共TreeCell呼叫(TreeView p){
TreeCell单元=新的TreeCell();
cell.setContextMenu(cm);
返回单元;
}
});

您必须为每个单元格创建不同的上下文菜单:

this.fileTreeView.setCellFactory(new Callback<TreeView<FileShort>,TreeCell<FileShort>>(){
    @Override
    public TreeCell<FileShort> call(TreeView<FileShort> p) {
        TreeCell<FileShort> cell = new TreeCell<FileShort>() {
            @Override
            protected void updateItem(FileShort file, boolean empty) {
                super.updateItem(file, empty);
                if (empty) {
                    setText(null);
                } else {
                    // maybe use a more appropriate string for display here
                    // e.g. if you were using a regular java.io.File you would
                    // likely want file.getName()
                    setText(file.toString());
                }
            }
        };
        ContextMenu cm = createContextMenu(cell);
        cell.setContextMenu(cm);
        return cell;
    }
});

private ContextMenu createContextMenu(TreeCell<FileShort> cell) {
    ContextMenu cm = new ContextMenu();
    MenuItem openItem = new MenuItem("Open File");
    openItem.setOnAction(event -> {
        FileShort file = cell.getItem();
        if (file != null) {
            // open the file...
        }
    });
    cm.getItems().add(openItem);
    // other menu items...
    return cm ;
}
this.fileTreeView.setCellFactory(新回调(){
@凌驾
公共TreeCell呼叫(TreeView p){
TreeCell单元=新的TreeCell(){
@凌驾
受保护的void updateItem(FileShort文件,布尔值为空){
super.updateItem(文件,空);
if(空){
setText(空);
}否则{
//可能使用更合适的字符串在此处显示
//例如,如果您使用的是常规的java.io.File,您会
//可能需要文件.getName()
setText(file.toString());
}
}
};
ContextMenu cm=createContextMenu(单元格);
cell.setContextMenu(cm);
返回单元;
}
});
私有上下文菜单createContextMenu(TreeCell单元格){
ContextMenu cm=新建ContextMenu();
MenuItem openItem=新MenuItem(“打开文件”);
openItem.setOnAction(事件->{
FileShort file=cell.getItem();
如果(文件!=null){
//打开文件。。。
}
});
cm.getItems().add(openItem);
//其他菜单项。。。
返回cm;
}

您是在向树单元注册上下文菜单吗?您的意思是让createNode为每个节点创建一个包含文件名的派生类的菜单项?也就是说,每个项目都有单独的上下文菜单?嗯,没有。我真的不理解那个评论。您发布的代码只是展示了如何构造上下文菜单。您没有显示您在哪里使用它,即您在哪里做
something.setContextMenu(cm)
something.setOnContextMenuRequested(事件->cm.show(…)或类似的东西。如果
something
是相关的树单元,则可以从该单元获取树项并执行所需操作。(但是每个单元格(不是项目)都有单独的上下文菜单,是的。)我正在将上下文菜单附加到树视图。。我不知道如何将单独的元素附加到树元素,因为treeview元素是动态生成的。是的,您需要将一个上下文菜单附加到每个
TreeCell
s,如果您在树上设置一个单元格工厂,您可以这样做。谢谢,这看起来可以工作。但是我有一个问题:树中的所有项目都显示为空白,即我只看到没有文件名和目录名的箭头。@Adder听起来好像您没有覆盖
updateItem(…)
方法。(为了简洁起见,我假设您只是在问题的代码中省略了它。)在答案中添加了一个示例实现缺少
cm.getItems().addAll(openItem)
public void setContextMenu(ContextMenu cm) 
{
    fileTreeView.setContextMenu(cm);
}
this.fileTreeView.setCellFactory(new Callback<TreeView<FileShort>,TreeCell<FileShort>>(){
    @Override
    public TreeCell<FileShort> call(TreeView<FileShort> p) {
        TreeCell<FileShort> cell = new TreeCell<FileShort>();
        cell.setContextMenu(cm);
        return cell;
    }
});
this.fileTreeView.setCellFactory(new Callback<TreeView<FileShort>,TreeCell<FileShort>>(){
    @Override
    public TreeCell<FileShort> call(TreeView<FileShort> p) {
        TreeCell<FileShort> cell = new TreeCell<FileShort>() {
            @Override
            protected void updateItem(FileShort file, boolean empty) {
                super.updateItem(file, empty);
                if (empty) {
                    setText(null);
                } else {
                    // maybe use a more appropriate string for display here
                    // e.g. if you were using a regular java.io.File you would
                    // likely want file.getName()
                    setText(file.toString());
                }
            }
        };
        ContextMenu cm = createContextMenu(cell);
        cell.setContextMenu(cm);
        return cell;
    }
});

private ContextMenu createContextMenu(TreeCell<FileShort> cell) {
    ContextMenu cm = new ContextMenu();
    MenuItem openItem = new MenuItem("Open File");
    openItem.setOnAction(event -> {
        FileShort file = cell.getItem();
        if (file != null) {
            // open the file...
        }
    });
    cm.getItems().add(openItem);
    // other menu items...
    return cm ;
}