我正在尝试接收JavaFX 2.2中一个不可见节点的MouseEvents。可以把它想象成一个互动但不可见的区域,比如当鼠标悬停在它上面时,它会触发一个动作。问题是,这不是一个静态定义的区域,但有多个区域(很多)可以被应用程序移动和调整大小。所以对于我的用例来说,全局监听鼠标移动并手动检测鼠标移动事件会有很大的开销。
目前,我正在试验一个透明矩形(新矩形(200100,Color.transparent)
),但实际/最终的应用程序将使用某种窗格,因为它实际上是其他组件的可拖动容器(当没有装满组件时,它具有透明区域,并且必须在这些透明区域上检测鼠标移动)。
此外,我还希望有人能帮助我更好地理解JavaFX 2.2通常是如何根据节点的可见性来处理MouseEvents的。
到目前为止,我的实验显示了以下一般见解:
>
给定透明场景:当用户单击透明区域时,鼠标事件将仅传递给外部应用程序(在场景下方可见)。当用户单击场景的可见像素时,无法将鼠标事件“传递到操作系统”。正当
默认情况下,位于其他节点顶部的窗格会吞掉任何MouseEvent,除非它是MouseTransparent或者MouseClick出现在不可见(透明)的区域。
pickOnBounds(true|false)
用于启用鼠标事件(true
)基于边界(矩形)的检测或禁用它(false
)。后者仅有效地处理可见像素/区域的鼠标事件。pickOnBounds(true)
似乎不适用于完全不可见的节点。右?
我的实验表明,节点至少需要填充-<code>新颜色(1,1,1.0.004)</code>才能被视为可见。较低的alpha值被认为是不可见的,这会导致不处理MouseEvents,即使调用了<code>pickOnBounds(true)</code>也是如此。
我说得对吗?那么一个看不见的节点就没有办法接收 MouseEvents。
或者 pickOnBounds
是否有特殊要求才能工作?我是否需要在节点显示或类似内容后才调用它?还有其他建议吗?
简而言之:使用node . set capacity(0.0)
不透明度属性控制节点的“视觉透明度”,而不影响它接收事件的能力,请参阅APIdocs。将此属性设置为零可实现您(和我)正在寻找的效果:一个不可见但鼠标敏感的“热区”——节点。
这与我首先尝试的< code > node . set visible(false)形成对比。这种方法还会禁用事件处理。From Node.setVisible() APIdocs:
不可见节点从不接收鼠标事件或键盘焦点,并且在不可见时从不保持键盘焦点。
“不可见”实际上意味着“在调用setViable(false)
之后”,不应与图像中的不透明度或全透明像素混淆。
由于缺乏声誉,我无法直接发布屏幕截图,因此:链接到显示以下示例代码的热区布局的屏幕截图(由于明显的原因,节点的不透明度在屏幕截图中未设置为0)。
该示例使用组作为热区,其中包含一个矩形和一个圆圈来定义捕获鼠标事件的区域。不透明度属性和鼠标处理程序只需要在组上设置,而不是在组的子项上设置。
这样您就可以构造任意形状的热区。如果您想使用具有透明区域的图像作为热区,则需要将其picOnBound
属性设置为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或者MouseClick出现在不可见(透明)的区域。
我也是这样理解的;但不确定鼠标是否进入/退出。对于这些,您可以至少在父级中监听<code>MOUSE_ENTERED_TARGET/MOUSE_ EXITED_TARGET</code>以确定哪个子级被输入/退出。如果要阻止子级接收事件,请在父级上注册事件筛选器并在那里使用事件。
pickOnBounds(true |false)用于启用(true)基于边界的(矩形)鼠标事件检测或禁用(false)。后者仅有效地处理可见像素/区域的鼠标事件。
是的。
pickOnBounds(true)似乎不适用于完全不可见的节点。
True用于通过调用setIn可见(true)
使节点不可见。
我的实验表明,一个节点至少需要填充-new Color(1,1,1,0.004)才能被认为是可见的。
无可奉告,但你的实验结果似乎不错。
那么不可见的节点将无法接收MouseEvents。
使用.setOpacity(0.0)
使节点“视觉上不可见”,但仍接收事件并遵守SetBickBounds
我准备好为此拔掉头发了。我正在开发游戏图形用户界面,它有一个由网格单元组成的地图。 单元格网格由StackPane组成,然后由ImageView或Shapes等组成的几个层组成。 整个内容包含在GridPane中,GridPane包含BorderPane的中心元素; 我不能在底层场景中添加鼠标事件,因为所有节点都会得到它- 下面是创建堆栈的代码: 这是设置EventHandler的代码- 谢谢你的
我要在两个图像视图之间绘制路径,视图与图片相同 此路径从其中一个imageview开始(按鼠标),继续(按鼠标)并在窗格上移动事件,并且必须在另一个imageview结束(按鼠标)。这是第一次鼠标按下在imageviews上没有收到任何鼠标按下事件后的问题,该事件只是在窗格上收到,因为绘制线没有停止。我的代码出了什么问题? 这是我的控制器代码: 请帮帮我。
我正在构建一个Java应用程序。这个应用程序是一个典型的“油漆”应用程序,你可以选择一种颜色,并在画布上绘制。除了...我将有一个圆圈数组分布在画布的顶部。我希望这些圆立即改变颜色,如果,当用户正在绘制和鼠标得到圆的X(10)个像素(其中X是绘制的线的宽度除以2)。 这是我的密码。我有一张画布是一组的一部分。我还创建了一个圆圈节点,并将其作为组的一部分。我想我需要以某种方式创建一个鼠标事件,当用户
正在处理自定义文件上载应用程序。我有两个主要问题: 下面给出的代码不会打开Mozilla和IE的文件对话框。 在Chrome中它起作用了,但是当我第一次点击就选择文件时,它从不将文件添加到正文中。但在第二次单击时,它会将第一次单击时浏览的文件添加到正文中。 对以上问题的任何帮助都将不胜感激。
在本章中,我们将详细介绍鼠标事件及其属性。 请注意:此类事件不仅可能来自于“鼠标设备”,还可能来自于对此类操作进行了模拟以实现兼容性的其他设备,例如手机和平板电脑。 鼠标事件类型 我们已经见过了其中一些事件: mousedown/mouseup 在元素上点击/释放鼠标按钮。 mouseover/mouseout 鼠标指针从一个元素上移入/移出。 mousemove 鼠标在元素上的每个移动都会触发此
鼠标事件的种类 鼠标事件指与鼠标相关的事件,继承了MouseEvent接口。具体的事件主要有以下一些。 click:按下鼠标(通常是按下主按钮)时触发。 dblclick:在同一个元素上双击鼠标时触发。 mousedown:按下鼠标键时触发。 mouseup:释放按下的鼠标键时触发。 mousemove:当鼠标在一个节点内部移动时触发。当鼠标持续移动时,该事件会连续触发。为了避免性能问题,建议对该