【问题标题】:JavaFX MenuItem does not react on MouseEvent.CLICKEDJavaFX MenuItem 对 MouseEvent.CLICKED 没有反应
【发布时间】:2016-05-16 17:50:46
【问题描述】:

我正在根据此处的 Oracle 示例编写一个带有 TreeView 的小型桌面应用程序:https://docs.oracle.com/javafx/2/ui_controls/tree-view.htm

从 ContextMenu 的 MenuItem 操作,我想触发一个事件,该事件将在我打开 ContextMenu 的项目下方创建一个新的 TreeItem。

对于 MenuItem,可以使用 setOnAction(EventHandler<ActionEvent> event) 方法,但我只想通过单击鼠标左键触发操作。

首先,不能将 EventHandler 添加到 MenuItem,尽管它提供了带有事件类型 MouseEvent.ANY(或其他任何东西)的方法 addEventHandler(EventType type, EventHandler<EventType> handler)。未调用事件处理程序的句柄方法。

其次,我可以通过menuItem.setGraphic(label) 向 MenuItem 添加标签并在标签中添加 EventHandler 来使用解决方法。尽管 MouseEvent.MOUSE_CLICKED 没有被标签上的 EventHandler 的句柄方法调用,但这个方法有效。

这是“正常”行为吗?我知道标签不会对点击事件做出反应,但我不明白为什么不能在 MenuItem 上注册单独的 EventHandler 或 EventFilter。

【问题讨论】:

    标签: java javafx


    【解决方案1】:

    ContextMenu 使用MenuItemContainer,这是一个

    容器负责在菜单中布置单行 - 在其他 换句话说,它包含并布置了一个 MenuItem,不管它是 特定的亚型。

    为了这个目的,它似乎创建了新的Nodes 代表MenuItem。所以任何添加到MenuItemEventHandlers 都不会被调用。

    要使其按预期工作,您可以使用CustomMenuItem 并将相应的EventHandler 添加到其content

     public class ContextMenuCell extends TreeCell<String> {
    
            private ContextMenu menu;
    
            public ContextMenuCell() {
                Label lbl = new Label("Add item");
                MenuItem menuItem = new CustomMenuItem(lbl);
    
                lbl.setOnMouseClicked(evt -> {
                    if (evt.getButton() != MouseButton.PRIMARY) {
                        return;
                    }
    
                    TreeItem treeItem =
                            new TreeItem<String>("New item");
    
                    if (getTreeItem().isLeaf()) {
                        getTreeItem().getParent().getChildren().add(getIndex(), treeItem);
                    } else {
                        getTreeItem().getChildren().add(0, treeItem);
                    }
    
                });
    
                menu = new ContextMenu(menuItem);
            }
    
            @Override
            public void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
    
                if (empty) {
                    setText(null);
                    setGraphic(null);
                } else {
                    setText(item);
                    setGraphic(getTreeItem().getGraphic());
                    setContextMenu(menu);
                }
            }
        }
    

    【讨论】:

    • 您的解决方案也适用于我,谢谢。似乎此时 API 还不是 100% 清楚,因为 packackge javafx.scene.control 中的许多控件可以处理单独的 EventHandler 和 EventFilter。
    【解决方案2】:

    MenuMenuItem 不是Nodes,因此它们不会处理鼠标点击,因为它们不会显示在屏幕上。一种解决方法是将图形对象 (Node) 设置为 MenuItem,并将侦听器添加到此 Node。也适用于 CheckMenuItem 等其他菜单:

    public class RunJavaFX extends Application {
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
    
    @Override
    public void start(Stage primaryStage) throws Exception {
        //the label will be our graphics object (Node)
        Label l = new Label("Your Menu Text");
        l.setTextFill(Color.BLACK); //set black since default CSS Style sets it to background color of the Menu
        //add either over addEventFilter or addEventHandler        
        l.addEventFilter(MouseEvent.MOUSE_PRESSED, ev -> {
                     if (ev.getButton() == MouseButton.SECONDARY) {
                         System.out.println("RightClick: " + ev.getSource() + System.nanoTime());                         
                     } else {
                         System.out.println("Not Right Click: " + ev.getSource() + System.nanoTime());
                     }
                     ev.consume(); //optional
                 });
        //create the MenuItem with an empty text and set the label l as graphics object
        MenuItem mI = new MenuItem("", l);
        //create the dummy menu and MenuBar for the example
        Menu m = new Menu("Menu");        
        m.getItems().add(mI);
        MenuBar mB = new MenuBar(m);
        //create the dummy scene for the example
        Scene scene = new Scene(mB);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多