JavaFX透明窗口仅接收绘制像素上的鼠标事件 [英] JavaFX transparent window only receives mouse events over drawn pixels

查看:147
本文介绍了JavaFX透明窗口仅接收绘制像素上的鼠标事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个与完全透明的屏幕大小相同的舞台,并在任何地方接收鼠标事件。在下面的示例中,仅当鼠标位于圆圈上时才会收到鼠标事件。我在Windows XP和Windows 7上使用Java 8u11看到了这个问题

I'd like a Stage that is the same size as the screen which is fully transparent and receives mouse events anywhere. In the example below I get mouse events only when the mouse is over the circle. I see this issue on both Windows XP and Windows 7 using Java 8u11

import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class TransparentTest extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage ignored) throws Exception {
        Stage stage = new Stage(StageStyle.TRANSPARENT);
        stage.setTitle("Transparent app test");

        Rectangle2D screenBounds = Screen.getPrimary().getBounds();
        stage.setX(0);
        stage.setY(0);
        stage.setWidth(screenBounds.getWidth());
        stage.setHeight(screenBounds.getHeight());

        Circle circle = new Circle(100);
        circle.setFill(Color.RED);
        Rectangle rectangle = new Rectangle(screenBounds.getWidth(),
                screenBounds.getHeight());
        rectangle.setFill(Color.TRANSPARENT);
        Scene scene = new Scene(new StackPane(circle, rectangle));
        scene.setFill(null);
        stage.setScene(scene);

        scene.setOnMouseMoved((e) -> {
            System.out.println("Mouse over rectangle " + e);
        });
        stage.show();
    }
}

有趣的是,如果我设置填充颜色的alpha部分到它的绝对最小值然后我得到鼠标事件。但是,我不想使用这种解决方法,实际上是问题的根源。我的结论是在JavaFX或Windows库中的某处,有一些命中检测代码可根据鼠标事件的像素值过滤鼠标事件。

Interestingly if I set the alpha part of the fill color to its absolute minimum then I get mouse events. However I'd prefer not to use this workaround and actually get to the bottom of the issue. My conclusion is somewhere in JavaFX or a Windows library there is some hit-detection code that filters mouse events based on the pixel value of the mouse event.

 rectangle.setFill(Color.rgb(0, 0, 0, 1d / 255d)); // receives mouse events        
 rectangle.setFill(Color.rgb(0, 0, 0, 0));         // does not receive mouse events

研究


  • JavaFx透明窗口 - 是请。鼠标透明 - 不,谢谢描述了类似的问题,但它没有解决完全透明区域中鼠标事件的问题

  • 调试 - 在setOnMouseMoved()中使用断点我已经检查了前面的堆栈框架以尝试查找命中检测代码。

  • 使用JNA测试不同的样式,例如WS_EX_TRANSPARENT和WS_EX_LAYERED。有趣的是,WS_EX_TRANSPARENT使窗口完全透明鼠标 - 在绘制的像素上没有鼠标事件。

  • 尝试将鼠标监听器放在矩形/ StackPane上 - 没有区别

  • MSDN文章分层Windows 提示此功能属于Windows而不是JavaFX。如果这是真的有任何解决方法吗?

  • JavaFx Transparent window - yes please. Mouse transparent - no thanks describes a similar problem, however it does not address the issue of mouse events in completely transparent areas
  • Debugging - using a breakpoint in the setOnMouseMoved() I've examined the preceding stackframes to try to find the hit-detection code.
  • Used JNA to test different styles such as WS_EX_TRANSPARENT and WS_EX_LAYERED. Interestingly WS_EX_TRANSPARENT made the window fully mouse transparent - no mouse events over the painted pixels.
  • Tried putting the mouse listener on the rectangle/StackPane instead - no difference
  • MSDN article Layered Windows hints at this functionality being part of Windows rather than JavaFX. If this is true is there any workaround?

分层窗口的命中测试基于形状透明度
窗口。这意味着窗口中
颜色键或其alpha值为零的区域将让鼠标消息
通过。如果分层窗口具有WS_EX_TRANSPARENT扩展
窗口样式,则将忽略分层窗口的形状,并将
鼠标事件传递到
分层窗口下的其他窗口。

Hit testing of a layered window is based on the shape and transparency of the window. This means that the areas of the window that are color-keyed or whose alpha value is zero will let the mouse messages through. If the layered window has the WS_EX_TRANSPARENT extended window style, the shape of the layered window will be ignored and the mouse events will be passed to the other windows underneath the layered window.


推荐答案

总之,只有已知的解决办法是将背景设置为对傻瓜不太透明 JavaFX发送事件。

In summary only known solution is to set the background to be "not quite" transparent to fool JavaFX into sending events.

rectangle.setFill(Color.rgb(0, 0, 0, 1d / 255d)); // receives mouse events

这篇关于JavaFX透明窗口仅接收绘制像素上的鼠标事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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