设置和重置上下文菜单JavaFX

时间:2014-02-10 03:42:52

标签: menu javafx

我想为右键单击+ ALT事件提供特殊的上下文菜单。

到目前为止,我可以将该事件的菜单设置为我的自定义菜单。但我无法在常规右键单击时将其重置为默认值(没有ALT关闭)。

我尝试通过textarea.getContextualMenu()存储默认菜单,并使用该菜单进行常规右键单击,但它仍然显示我的自定义菜单,包括有和没有ALT的两个事件。

关于如何重置菜单的任何想法?

//store default menu
        defaultMenu = controller.txtArea.getContextMenu();
        //check if alt is down
        controller.txtArea.addEventHandler(KeyEvent.KEY_PRESSED, new    EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent keyEvent) {
                if (keyEvent.getCode().equals(ALT)) {                 
                    System.out.println("alt typed---" + controller.txtArea.getCaretPosition());

                    //check if right click is performed
                    controller.txtArea.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent mouseEvent) {
                            if (mouseEvent.getButton().equals(MouseButton.SECONDARY)) {
                                //override default menu by custom one
                                ContextMenu customMenu = new ContextMenu(new MenuItem("testing"));
                                controller.txtArea.setContextMenu(customMenu);   
                            }
                        }
                    });
                }

                else{
                    //reset menu to default
                    controller.txtArea.setContextMenu(defaultMenu);
                }

            }
        });

3 个答案:

答案 0 :(得分:2)

我会在the menu requested event.

中将其切换(或根据情况构建一个)

我根据具体情况做这样的事情来构建菜单。不完全是您的情况,但您可以在事件处理程序中设置不同的菜单。它是Node的一种方法,因此您可以将它用于TextArea。

private static final class TextFieldTreeCellImpl extends TreeCell<String> {

    private TextField textField;
    public TextFieldTreeCellImpl() {
        setOnContextMenuRequested((ContextMenuEvent event) -> {
            setContextMenu(getCtxMenu());
        });
    }
    private ContextMenu getCtxMenu() {
        ContextMenu ctxMenu = new ContextMenu();
        ((TreeNode)getTreeItem()).addMenuItems(ctxMenu);
        return ctxMenu;
    }
...

答案 1 :(得分:1)

你的问题非常有趣。虽然您尚未提交应用程序代码以便我们可以精确地分析问题,但我可以向您介绍另一种解决方案(可能更好)。

我很少次使用上下文菜单。也许你可以做一些更有趣的事情。例如,您可以仅使用JavaFX组件的联结创建上下文菜单。为此,您可以在程序中定义一个区域,该区域将保留用于上下文菜单的外观。该区域可能是JavaFX组件(控件),例如文本区域。您可以从此控件上应用鼠标事件开始。用户点击鼠标后,您可以显示自己的上下文菜单。

您可以创建Parent类的扩展,该扩展可用作放置JavaFX控件的区域。使用new CSS API,您可以通过CSS为这个控件放置区域设置样式。将所有控件放在该区域之后,您将拥有上下文菜单。当您在文本区域中单击鼠标时,在上下文菜单中使用控件,您可以显示自己的上下文菜单。

要正确完成此操作,您可以在应用程序的开头通过将opacity property设置为零并将mouseTransparent设置为true来在文本区域的同一集合中添加上下文菜单。当用户点击时,触发的事件必须更改这些属性,并使用layoutXY properties正确定位上下文菜单。或者你不能使用opacity和mouseTransparent。您可以在必要时添加和删除上下文菜单。

为了让您的程序变得更好,您可以使用Timeline添加不透明度动画,逐渐显示您的自定义上下文菜单。您还可以添加着色效果,例如DropShadow,这会使您的上下文菜单明显高于文本区域。

这将为您提供更多灵活性和自定义,使您的应用程序更具吸引力。 ;)

答案 2 :(得分:0)

这是解决方案!感谢您的意见。 有两个问题:第一个是由setOnContextMenuRequested解决的上下文菜单。第二个是ALT被“按下”的事实,我不得不在没有按下时再发射一个事件......重新启动菜单。所以以下组合起作用:

        //add custom menu actions..
        controller.inLineCSSTextArea.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {//check for mouse click
            @Override
            public void handle(MouseEvent mouseEvent) {//handle event this way...
                if (mouseEvent.getButton().equals(MouseButton.SECONDARY)) {//if right mouse button
                    controller.inLineCSSTextArea.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {//check for context menu request
                        @Override
                        public void handle(ContextMenuEvent arg0) {//handle event this way...
                            //set a custom menu based on key event
                            controller.inLineCSSTextArea.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {//check for key event...
                                @Override
                                public void handle(KeyEvent keyEvent) {//handle event this way...
                                    if (keyEvent.getCode().equals(CONTROL)) {//if control key is pressed
                                        controller.inLineCSSTextArea.setContextMenu(CNTRLmenu);
                                    }
                                    if (keyEvent.getCode().equals(ALT) ) {//if alt key is pressed
                                        controller.inLineCSSTextArea.setContextMenu(ALTmenu);
                                    }

                                }
                            });

                        }
                    });
                }
            }
        });

        //reset the context menu when any key is released. this is needed, otherwise default menu will not be set again on right click.
        controller.inLineCSSTextArea.addEventHandler(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent keyEvent) {
                controller.inLineCSSTextArea.setContextMenu(DEFAULTmenu);
            }
        });