Javafx 2 JavaFX 2.2不可见节点的Mouseevent

Javafx 2 JavaFX 2.2不可见节点的Mouseevent,javafx-2,mouseevent,visibility,invisible,scenegraph,Javafx 2,Mouseevent,Visibility,Invisible,Scenegraph,我正在尝试接收JavaFX2.2中不可见节点的MouseEvents。将其视为一个交互式但不可见的区域,例如当鼠标悬停时,该区域会触发一个动作。问题是,这不是一个静态定义的分区,但有多个分区(很多)可以由应用程序移动和调整大小。因此,对于我的用例来说,全局监听鼠标移动并执行手动检测,比如说,MouseMove事件,会有很大的开销 目前,我正在试验一个透明矩形(新矩形(200100,Color.transparent)),但实际/最终应用程序将使用某种窗格,因为它实际上是其他组件的可拖动容器(如果

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

目前,我正在试验一个透明矩形(
新矩形(200100,Color.transparent)
),但实际/最终应用程序将使用某种窗格,因为它实际上是其他组件的可拖动容器(如果没有组件,则具有透明区域,并且必须在这些透明区域上检测鼠标移动)

此外,我还希望得到一些答案,帮助我更好地理解JavaFX2.2通常如何根据节点的可见性处理mouseevent

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

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

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

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

  • 我的实验表明,节点至少需要填充-
    新颜色(1,1,1,0.004)
    才能被视为可见。较低的alpha值被视为不可见,这会导致无法处理鼠标事件,即使调用了
    pickOnBounds(true)

我做对了吗?那么一个不可见的节点就无法接收MouseEvents

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

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

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

这与我首先尝试的
Node.setVisible(false)
不同。这种方法还禁用事件处理。从Node.setVisible()APIdocs:

不可见节点从不接收鼠标事件或键盘焦点,并且在不可见时从不保持键盘焦点

“不可见”实际上是指“调用
setVisible(false)
”之后,不应与图像中的不透明度或完全透明像素混淆

由于声誉不佳,我无法直接发布截图,因此: 这显示了下面示例代码的热区布局(由于明显的原因,在屏幕截图中节点的不透明度没有设置为0)

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

这样,您可以构建任意形状的热区。 如果要将具有透明区域的图像用作热区,则其
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);

    }
编辑:关于你的具体子问题(据我所知,我不是外汇大师:)

当用户单击时,无法将鼠标事件“传递到操作系统” 在场景的可见像素上。对吧?

有意思,我从没试过。一个关于什么可能起作用的纯粹猜测:获取鼠标事件的屏幕坐标,将窗口移到一边,使用java.awt.Robot将操作系统光标移动到鼠标事件的坐标,如果需要,在那里单击鼠标,然后将窗口移回。 当心:听起来像一个彻头彻尾的黑客

默认情况下,其他节点顶部的窗格将吞下任何MouseEvent 除非它是MouseTransparent或鼠标单击出现在 不可见(透明)区域

我也是这样理解的;但不确定鼠标是否进入/退出。对于那些您可以至少在父对象中收听
鼠标输入\鼠标目标/鼠标退出\鼠标目标
,以确定哪个子对象被输入/退出。如果要阻止子级接收事件,请在父级上注册事件筛选器并在那里使用事件

pickOnBounds(true | false)用于启用(true)基于 (矩形)检测鼠标事件或禁用鼠标事件(假)。后者的 仅对可见像素/区域有效处理鼠标事件

pickOnBounds(true)似乎不适用于完全不可见的节点

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

我的实验表明,一个节点至少需要一个新的填充 颜色(1,1,1,0.004)视为可见

无可奉告,但你的实验结果似乎不错

这样,不可见节点就无法接收MouseEvents

使用
.setOpacity(0.0)
可以使节点“视觉上不可见”,但仍然可以接收事件和荣誉值