javafx-2 - JavaFX 2.2 不可见节点的鼠标事件

标签 javafx-2 mouseevent visibility invisible scenegraph

我正在尝试接收 JavaFX 2.2 中不可见节点的 MouseEvents。将其视为一个交互式但不可见的区域,例如当鼠标悬停在其上时应触发操作。问题是,这不是静态定义的区域,而是有多个区域(很多)可以由应用程序移动和调整大小。因此,对于我的用例来说,全局监听鼠标移动并执行手动检测(例如 MouseMove-Events)会产生大量开销。

目前,我正在尝试使用透明矩形(new Rectangle(200, 100, Color.TRANSPARENT)),但实际/最终应用程序将使用某种 Pane ,因为它实际上是其他组件的可拖动容器(当未装满组件时,它具有透明区域,并且也必须在这些透明区域上检测到 MouseMoves)。

我另外希望能够帮助我更好地理解 JavaFX 2.2 通常如何根据节点的可见性处理 MouseEvents 的答案。

到目前为止,我的实验显示了以下一般见解:

  • 给定一个透明场景: 当用户单击透明区域时,鼠标事件只会传递到外部应用程序(视觉上位于场景下方)。当用户单击场景的可见像素时,无法将鼠标事件“传递给操作系统”。对吗?

  • 默认情况下,其他节点之上的 Pane 将吞没任何 MouseEvent,除非它是 MouseTransparent 或 MouseClick 出现在不可见(透明)区域。

  • pickOnBounds(true|false) 可以启用 (true) 基于边界(矩形)的 MouseEvents 检测或禁用它 (false) )。后者仅有效处理可见像素/区域的鼠标事件。 pickOnBounds(true) 似乎不适用于完全不可见的节点。对吗?

  • 我的实验表明,节点至少需要填充 - new Color(1,1,1,0.004) 才能被视为可见。较低的 alpha 值被视为不可见,这会导致即使调用了 pickOnBounds(true),也不会处理 MouseEvents。

我做对了吗?那么不可见的 Node 将无法接收 MouseEvents。

或者 pickOnBounds 的工作是否有特殊要求?我是否需要仅在显示节点或类似内容后调用它? 还有其他建议吗?

最佳答案

简而言之:使用 Node.setOpacity(0.0)

opacity 属性控制节点的“视觉透明度”,而不影响其接收事件的能力,请参阅 APIdocs 。将此属性设置为零可以实现您(和我)正在寻找的效果:一个不可见但对鼠标敏感的“热区”-节点。

这与我首先尝试的 Node.setVisible(false) 形成鲜明对比。该方法还会禁用事件处理。来自 Node.setVisible() API 文档:

Invisible nodes never receive mouse events or keyboard focus and never maintain keyboard focus when they become invisible.

“Invisible”实际上意味着“调用setVisible(false)之后”,不应与图像中的不透明或完全透明像素混淆。

由于缺乏声誉,我无法直接发布屏幕截图,因此: link to screenshot显示了下面示例代码的热区布局(出于明显的原因,屏幕截图中节点的不透明度未设置为 0)。

该示例使用一个 Group 作为热区,其中包含一个矩形和一个圆形来定义捕获鼠标事件的区域。只需要在 Group 上设置不透明度属性和鼠标处理程序,而不是在其子组上设置。

这样你就可以构建任意形状的热区。 如果您想使用具有透明区域的图像作为热区,则需要将其 pickOnBounds 属性设置为 false,以便考虑实际图像内容,而不仅仅是边界框。

希望对你有帮助!

public class HotZoneTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        StackPane root = new StackPane();
        Scene scene = new Scene(root, 300, 250);
        primaryStage.setScene(scene);
        primaryStage.show();

        Group hotZone = new Group();
        root.getChildren().add(hotZone);

        hotZone.getChildren().add(new Rectangle(10, 20, 100, 50));
        hotZone.getChildren().add(new Circle(50, 120, 20));

        hotZone.setOpacity(0.4); //set to 0.0 to make invisible

        EventHandler handler = new EventHandler() {
            @Override
            public void handle(Event e) {
                System.out.println("hotZone mouse event: " + e);
            }
        };
        hotZone.addEventHandler(MouseEvent.MOUSE_ENTERED, handler);
        hotZone.addEventHandler(MouseEvent.MOUSE_CLICKED, handler);
        hotZone.addEventHandler(MouseEvent.MOUSE_EXITED, handler);

    }

编辑:关于您的具体子问题(据我所知,我不是外汇专家:))

There's no way to pass a mouse-event "to the OS" when the user clicks on a visible pixel of the Scene. Right?

有趣,从未尝试过。对可能有效的纯粹猜测:获取鼠标事件的屏幕坐标,将窗口移开,使用 java.awt.Robot 将操作系统光标移动到鼠标事件的坐标,如果需要,单击此处,然后移动您的窗口 window 后面。 当心:听起来完全是黑客行为!

A Pane on top of other nodes will per default swallow any MouseEvent unless it is MouseTransparent or the MouseClick appears on a non-visible (transparent) area.

我也是这么理解的;但不确定鼠标进入/退出。对于那些您可以至少在父级中监听 MOUSE_ENTERED_TARGET/MOUSE_EXITED_TARGET 以确定哪个子级进入/退出的情况。如果您想阻止子级接收事件,请在父级上注册事件过滤器并在那里使用事件。

pickOnBounds(true|false) is there to enable (true) bounds-based (rectangular) detection of MouseEvents or disable it (false). Latter effectively handles mouse-events only for visible pixels / areas.

是的。

pickOnBounds(true) seems not to work for completely invisible nodes.

对于通过调用 setInvisible(true) 使节点不可见的节点为 True。

My experiments have shown, that a node needs at least a fill of - new Color(1,1,1,0.004) to be considered visible.

无法发表评论,但您的实验结果似乎不错。

Then there would be no way for an invisible Node to receive MouseEvents.

使用.setOpacity(0.0)使节点“视觉上不可见”,但仍然接收事件并遵循setbickOnBounds

关于javafx-2 - JavaFX 2.2 不可见节点的鼠标事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25384917/

相关文章:

c# - 嵌套类构造函数的可见性

javascript - 如何通过单击隐藏在 JavaScript 中的 div 来触发函数?

java - 如何在eclipse kepler中添加javafx插件

Java:在当前目标上应用样式的方法

python - 如何模拟游戏中的鼠标移动?

java - 输入标签时鼠标跳跃

java - 在 JavaFX 2.0 单元格的文本属性中突出显示子字符串

java - 如何在javafx2中获取变换后的形状的坐标?

google-maps-api-3 - 谷歌地图——在点击事件期间检测metaKey状态?

即使将其可见性设置为 GONE,Android View 仍会获得 OnClick()