【问题标题】:Is there a way to access ContextMenu scroll arrows (scroll bar) ? JavaFX有没有办法访问 ContextMenu 滚动箭头(滚动条)? JavaFX
【发布时间】:2020-04-28 11:27:59
【问题描述】:

我在这里根据这个答案实现自动完成文本字段:

https://stackoverflow.com/a/40369435/9047625

我使用高度足够长的 ContextMenu,因此一次可以看到约 15 个项目,当有更多可用项目时,上下文菜单的底部和顶部会显示箭头。

我遇到的问题是,当我向下滚动项目并输入一些其他单词时,我的上下文菜单仍然向下滚动,即使只有 1 个项目,我也必须手动向上滚动以显示项目。

我尝试了不同的方法来访问 ContextMenu 的滚动条,所以每次我在字段中输入一个新字符时,我都可以将它滚动到顶部,但我想不出这样做的方法..

每当我在字段中输入内容以自动完成时,是否有任何方法可以向上滚动上下文菜单或将焦点设置到第一个元素(顶部)?

我希望我能正确解释我的问题,我很感谢提前回复..

【问题讨论】:

    标签: java javafx autocomplete contextmenu


    【解决方案1】:

    ContextMenu 保留一个向上和向下箭头作为 MenuItem 的一种特殊类型,称为 ArrowMenuItem。结构如下:

    ContextMenu > ContextMenuSkin > ContextMenuContent > ArrowMenuItem
    

    ArrowMenuItem 是一个非静态包私有类。 ContextMenuContent 有两个此类的实例:upArrowdownArrow,这两个实例仅在项目无法放入 ContextMenu 时显示。 ContextMenuContent 使用Timeline 滚动ContextMenu,因此当ENTERED 类型MouseEvent 被触发时,Timeline 开始根据悬停的@987654336 向上或向下滚动内容@。 Timeline 在鼠标离开该区域时停止。 ContextMenuContent 有一个方法 scroll 就是你所需要的,但不幸的是,这个方法是不公开的。

    可能的解决方案:

    1. 扩展ContextMenuSkinContextMenuContent 以公开方法scroll。这样,您可以从皮肤中调用查找ContextMenuContent 并使用该方法一直向上或向下滚动。

    2. 使用menu-up-arrowmenu-down-arrow 样式类来查找箭头节点。获得箭头节点后,您可以刺激鼠标ENTERED 事件以使ContextMenu 向上或向下滚动。请注意,这样用户必须等到滚动完成,因为Timeline 具有固定的滚动速率。然后你需要在滚动结束后消费这个事件。 示例代码:

    ContextMenuSkin skin = (ContextMenuSkin) contextMenu.getSkin();
    Node up = skin.getNode().lookup(".menu-up-arrow");
    Node down = skin.getNode().lookup(".menu-down-arrow");
    MouseEvent enteredEvent = new MouseEvent(MouseEvent.MOUSE_ENTERED, ...); // the remaining parameters
    if (shouldScrollUp) {
        up.fireEvent(enteredEvent);
    } else {
        down.fireEvent(enteredEvent);
    }
    // consume the event after scroll is over
    
    1. 使用反射:
    private static void scrollContextMenuUp(ContextMenu contextMenu) {
        try {
            ContextMenuSkin skin = (ContextMenuSkin) contextMenu.getSkin();
            ContextMenuContent content = (ContextMenuContent) skin.getNode();
            Method method = content.getClass().getDeclaredMethod("scroll", double.class);
            method.setAccessible(true);
            method.invoke(content, 12.0); // change this double value to scroll more
        } catch (Exception e) {
            System.err.println("Unable to scroll due to: " + e.getMessage());
        }
    }
    

    【讨论】:

    • 我已经从我的自定义上下文菜单中扩展了 ContextMenu,所以我可以设置它的高度。我不完全确定扩展 ContextMenu Skin、ContextMenuContent 是什么意思,因为我不能从我的类中扩展多个类?
    • 抱歉发了双份,我在手机上,我真的很想用第一个解决方案,如果我想不通,我会选择第二个,我只是想问u 我怎么知道滚动实际上何时结束并且我可以消费该事件?非常感谢你,我已经为此苦苦挣扎了很长时间,我真的很感谢你有时间回答这个问题
    • 对于第一种解决方案,滚动方法似乎具有默认访问修饰符,因此我无法从不同的包访问它..:/
    • 您可以覆盖createDefaultSkin() 以返回您自己的ContextMenuSkin。你用的是什么版本的JDK?
    • 我正在使用 jdk1.8.0_221。我看到我可以从我的扩展 ContextMenu 的类中覆盖 createDefaultSkin()(我这样做是为了设置上下文菜单的高度)。但我不明白如何访问滚动方法。再次感谢您的帮助,我真的很感激
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-13
    • 1970-01-01
    • 2017-03-23
    • 2013-11-03
    • 2021-09-10
    • 2021-01-02
    相关资源
    最近更新 更多