可见节点的JavaFX 2.2 Mouseevent [英] JavaFX 2.2 Mouseevent for invisible node

查看:99
本文介绍了可见节点的JavaFX 2.2 Mouseevent的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to receive MouseEvents for an invisible node in JavaFX 2.2. Think of it as an interactive but invisible Zone that should trigger an action for example when the mouse hovers it. The problem is, that this is not a statically defined zone, but there are multiple zones (a lot of it) that can be moved and resized by the application. So for my use-case it would be a lot of overhead to globally listen to mouse-movement and perform a manual detection of - say - MouseMove-Events.

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

Currently, I'm experimenting with a transparent Rectangle (new Rectangle(200, 100, Color.TRANSPARENT)), but the actual / final Application will use some sort of a Pane for it, because it's actually a draggable container for other components (when not full of components, it has transparent areas and MouseMoves must be detected on these transparent areas as well).

我还希望得到一些答案,这些答案有助于我更好地了解JavaFX 2.2通常如何根据节点的可见性来处理MouseEvent.

I additionally would appreciate answers that help me to get a better understanding of how JavaFX 2.2 generally handles MouseEvents depending on the visibility of nodes.

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

My experiments have shown the following general insights so far:

  • 给出一个透明的场景:当用户单击透明区域时,鼠标事件将仅传递给外部应用程序(在场景下方,以可视方式显示).当用户单击场景的可见像素时,无法将鼠标事件传递给OS".对吧?

  • Given a transparent Scene: Mouse Events will only be passed to foreign Applications (visually below the Scene) when the user clicks on a transparent area. There's no way to pass a mouse-event "to the OS" when the user clicks on a visible pixel of the Scene. Right?

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

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.

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

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. Right?

我的实验表明,一个节点至少需要填充- new Color(1,1,1,0.004)才能被视为可见.较低的alpha值被认为是不可见的,即使已调用 pickOnBounds(true),也会导致无法处理MouseEvent.

My experiments have shown, that a node needs at least a fill of - new Color(1,1,1,0.004) to be considered visible. Lower alpha-values are considered invisible, which causes MouseEvents not to be handled, even if pickOnBounds(true) has been called.

我说对了吗?然后,看不见的节点将无法接收MouseEvent.

Did I get this right? Then there would be no way for an invisible Node to receive MouseEvents.

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

Or is there a special requirement for pickOnBounds to work? Do I need to call it only after the node has been shown or something similar? Any other suggestions?

推荐答案

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

opacity属性控制节点的视觉透明性"而不影响其接收事件的能力,请参见

The opacity property controls a Node's "visual transparency" without affecting it's ability to receive Events, see APIdocs. Setting this property to zero achieves the effect you (and I) were looking for: An invisible but mouse-sensitive "hot zone"-Node.

这与我首先尝试过的 Node.setVisible(false)相反.该方法还会禁用事件处理.从Node.setVisible()APIdocs:

This is in contrast to Node.setVisible(false) which I tried first. That approach also disables Event handling. From Node.setVisible() APIdocs:

不可见节点永远不会收到鼠标事件或键盘焦点,也永远不会保持键盘焦点.

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

不可见"实际上意味着在调用 setVisible(false)之后",并且不应与图像中的不透明度或完全透明的像素混淆.

"Invisible" there really means "after calling setVisible(false)" and should not be confused with opacity or fully transparent pixels in an image.

由于缺乏声誉,我无法直接发布屏幕截图,因此:链接到屏幕快照,其中显示了下面示例代码的热点区域布局(未设置节点的不透明度明显原因是屏幕截图中的0).

Due to lack of reputation I can't post a screenshot directly, so: link to screenshot that shows the hot zone layout of the example code below (the Node's opacity is not set to 0 in the screenshot for obvious reasons).

该示例使用组作为热点"区域,其中包含一个矩形和一个圆形,以定义捕获鼠标事件的区域.opacity属性和鼠标处理程序仅需要在Group上设置,而不是其子级.

The example uses a Group as hot zone which contains a rectangle and a circle to define the areas in which mouse events are captured. The opacity property and mouse handler only need to be set on the Group, not it's children.

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

That way you can construct arbitrarily shaped hot zones. If you want to use an image with transparent areas as a hot zone, its pickOnBounds property needs to be set to false so the actual image content is considered, not only the bounding box.

希望有帮助!

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);

    }

关于您的特定子问题(据我所知,我不是FX专家:))

edit: regarding your specific sub-qestions (all as far as I know, I'm not an FX guru :) )

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

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将OS光标移动到鼠标事件的坐标,如果需要,单击此处,然后移动窗后.当心:听起来像是完全骇客!

Interesting, never tried that. A pure speculation on what might work: Get screen coordinates of mouse event, move your window out of the way, use java.awt.Robot to move the OS cursor to coordinates of mouse event, fire a click there if needed, and move your window back. Beware: Sounds like a total hack!

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

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 来确定哪个孩子被输入/退出.如果要防止子级接收事件,请在父级上注册一个事件过滤器,并在该处使用该事件.

That's how I understand it, too; not sure about mouse enter/exit though. For those you can listen on MOUSE_ENTERED_TARGET/MOUSE_EXITED_TARGET at least in a parent to determine which child was entered/exited. Register an event filter on the parent and consume the event there if you want to prevent the child from receiving the event.

pickOnBounds(true | false)可以启用基于(true)界限的(矩形)检测MouseEvent或将其禁用(错误).后期仅针对可见像素/区域有效地处理鼠标事件.

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)对于完全不可见的节点似乎不起作用.

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

通过调用 setInvisible(true)使节点不可见.

True for Nodes made invisible by calling setInvisible(true).

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

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

无法发表评论,但是您的实验结果听起来不错.

Can't comment, but your experiment result seems sound.

然后,看不见的节点将无法接收MouseEvent.

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

使用 .setOpacity(0.0)可使节点在视觉上不可见",但仍会接收事件并尊重setbickOnBounds

Using .setOpacity(0.0) makes a Node "visually invisible", but still receive events and honor setbickOnBounds

这篇关于可见节点的JavaFX 2.2 Mouseevent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆