Javafx 2 JavaFX 2.2不可见节点的Mouseevent
我正在尝试接收JavaFX2.2中不可见节点的MouseEvents。将其视为一个交互式但不可见的区域,例如当鼠标悬停时,该区域会触发一个动作。问题是,这不是一个静态定义的分区,但有多个分区(很多)可以由应用程序移动和调整大小。因此,对于我的用例来说,全局监听鼠标移动并执行手动检测,比如说,MouseMove事件,会有很大的开销 目前,我正在试验一个透明矩形(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)),但实际/最终应用程序将使用某种窗格,因为它实际上是其他组件的可拖动容器(如果
新矩形(200100,Color.transparent)
),但实际/最终应用程序将使用某种窗格,因为它实际上是其他组件的可拖动容器(如果没有组件,则具有透明区域,并且必须在这些透明区域上检测鼠标移动)
此外,我还希望得到一些答案,帮助我更好地理解JavaFX2.2通常如何根据节点的可见性处理mouseevent
到目前为止,我的实验显示了以下一般性见解:
- 给定一个透明场景: 只有当用户单击透明区域时,鼠标事件才会传递给外部应用程序(在场景下方可见)。当用户单击场景的可见像素时,无法将鼠标事件“传递给操作系统”。对吗
- 默认情况下,其他节点顶部的窗格将吞下任何MouseEvent,除非它是MouseTransparent或MouseClick出现在不可见(透明)区域
可以启用(pickOnBounds(true | false)
)基于边界的(矩形)鼠标事件检测或禁用它(true
)。后者只对可见像素/区域有效地处理鼠标事件。false
似乎对完全不可见的节点不起作用。对吗pickOnBounds(true)
- 我的实验表明,节点至少需要填充-
才能被视为可见。较低的alpha值被视为不可见,这会导致无法处理鼠标事件,即使调用了新颜色(1,1,1,0.004)
pickOnBounds(true)
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)
可以使节点“视觉上不可见”,但仍然可以接收事件和荣誉值