【问题标题】:JavaFX transparent window only receives mouse events over drawn pixelsJavaFX 透明窗口仅在绘制的像素上接收鼠标事件
【发布时间】:2015-01-07 20:44:14
【问题描述】:

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

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 库中的某个地方,有一些命中检测代码可以根据鼠标事件的像素值过滤鼠标事件。

 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 Transparent window - yes please. Mouse transparent - no thanks 描述了一个类似的问题,但是它没有解决完全透明区域中的鼠标事件问题
  • 调试 - 在 setOnMouseMoved() 中使用断点我检查了前面的堆栈帧以尝试找到命中检测代码。
  • 使用 JNA 测试不同的样式,例如 WS_EX_TRANSPARENT 和 WS_EX_LAYERED。有趣的是 WS_EX_TRANSPARENT 使窗口完全鼠标透明 - 没有鼠标事件在绘制的像素上。
  • 尝试将鼠标侦听器放在矩形/StackPane 上 - 没有区别
  • MSDN 文章 Layered Windows 暗示此功能是 Windows 而不是 JavaFX 的一部分。如果这是真的,是否有任何解决方法?

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

【问题讨论】:

  • 作为比较:在 MacOS X 10.9.5 上,矩形也在透明区域上接收鼠标事件。所以它似乎更像是一个 Windows 特定的问题,而不是 JacaFX。
  • 在 Windows7 上,矩形也在透明区域接收到鼠标事件。你的 jdk 是什么版本的?
  • 8u11.我已经更新了这个问题。你用的是什么版本?
  • 我使用的是 8u20,但我已经下载了 jdk 8u11 并对其进行了测试......矩形也在透明区域接收到鼠标事件。
  • 我在 Windows 上使用 jre7.67,在 Linux 上使用 jre7.71,但我没有收到事件。任何新闻?这是一个已知的错误吗?

标签: java javafx javafx-8


【解决方案1】:

总而言之,唯一已知的解决方案是将背景设置为“不太”透明以欺骗 JavaFX 发送事件。

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

【讨论】:

    猜你喜欢
    • 2019-01-30
    • 2014-07-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-13
    • 2011-08-28
    • 2020-04-28
    • 2011-09-27
    相关资源
    最近更新 更多