JavaFx 透明窗口 - 是的,请。鼠标透明 - 不,谢谢

标签 java javafx-2 mouseevent transparency

我想创建一个简单的 JavaFx 类,向用户显示一个覆盖用户屏幕的半透明矩形(比如任意 50% 的透明度)。它应该只是让我获得鼠标单击事件的点。这听起来微不足道,但是当我创建透明窗口时,它们似乎总是对鼠标事件透明,而不仅仅是我对半透明可见性的要求。永远不会触发鼠标事件。

我在矩形和根 Pane 上使用了 setMouseTransparent(false),但这没有任何区别。如果有人能指出任何错误/误解,我将不胜感激。

这是我创建的简单测试类:

public class ClickScreen implements MouseListener {

    private ClickScreenListener listener;
    private Stage window;
    private Point point;

    public ClickScreen(ClickScreenListener listener) {

        // Get screen size
        Rectangle2D r = Screen.getPrimary().getBounds();

        // Something to put stuff in
        StackPane root = new StackPane();

        // Translucent rectangle on the pane
        Rectangle rectangle = new Rectangle(r.getWidth(), r.getHeight());
        rectangle.setFill(Color.rgb(183, 183, 183, 0.5));
        root.getChildren().add(rectangle);

        Scene scene = new Scene(root, r.getWidth(), r.getHeight());
        scene.setFill(null);

        window = new Stage();
        window.initStyle(StageStyle.TRANSPARENT);
        window.setTitle("Click drop location");
        window.setScene(scene);

        this.listener = listener;

    }

    public Point getLocation(){
        return point;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        point = e.getLocationOnScreen();
        listener.screenClicked(point);
    }
}

编辑: 我遇到的透明度问题的一个更简单的例子来自这个 Hello World!例子。当我将鼠标悬停在按钮上时,大约有 50:50 的机会单击按钮或仅单击“通过”并将焦点放在底层窗口(在我的情况下通常是 eclipse)。希望您对此有想法。

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

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Hello World!");
        Button btn = new Button();
        btn.setText("Say 'Hello World'");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                System.out.println("Hello World!");
            }
        });

        StackPane root = new StackPane();
        root.getChildren().add(btn);

        Scene scene = new Scene(root, 300, 250);
        scene.setFill(null);

        primaryStage.setScene(scene);
        primaryStage.initStyle(StageStyle.TRANSPARENT);
        primaryStage.show();
    }
}

最佳答案

检查您的导入

您正在使用某种奇怪的设置,其中混合了 AWT/Swing 类和 JavaFX 类,这确实是不被建议的(并且在您使用的组合和方式中根本不起作用)。请注意在您的 JavaFX 程序中不要导入任何 java.awt.*javax.swing.* 类,除非您真的知道您在将两个代码混合在一起时在做什么不同的工具包。

示例解决方案

这是一个示例解决方案,它仅导入 JavaFX 类并利用 JavaFX 事件,但在其他方面尝试坚持您问题中示例代码的编码/回调样式。 (该示例可以通过使用 Java 8 lambda 进一步简化)。

enter image description here

import javafx.application.Application;
import javafx.event.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.*;

public class ClickListenerSample 
                 extends Application 
                 implements ClickScreenListener {

    private Label clickFeedbackLabel = new Label("");

    @Override public void start(Stage stage) {
        Button listen = new Button("listen");
        listen.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                new ClickScreen(ClickListenerSample.this);
            }
        });
        VBox layout = new VBox(10);
        layout.getChildren().setAll(
            listen,
            clickFeedbackLabel
        );
        layout.setPadding(new Insets(10));

        stage.setScene(new Scene(layout, 100, 80));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

    @Override public void screenClicked(Point2D point) {
        clickFeedbackLabel.setText(point.getX() + ", " + point.getY());
    }
}

interface ClickScreenListener {
    void screenClicked(Point2D point);
}

class ClickScreen {
    private ClickScreenListener listener;
    private Stage window;
    private Point2D point;

    public ClickScreen(ClickScreenListener listener) {
        // Get screen size
        Rectangle2D r = Screen.getPrimary().getBounds();

        // Something to put stuff in
        StackPane root = new StackPane();
        root.setStyle("-fx-background-color: null;");

        // Translucent rectangle on the pane
        Rectangle rectangle = new Rectangle(r.getWidth(), r.getHeight());
        rectangle.setFill(Color.rgb(183, 183, 183, 0.5));
        root.getChildren().add(rectangle);

        Scene scene = new Scene(root, r.getWidth(), r.getHeight());
        scene.setFill(null);

        window = new Stage();
        window.initStyle(StageStyle.TRANSPARENT);
        window.setTitle("Click drop location");
        window.setScene(scene);

        scene.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                point = new Point2D(event.getScreenX(), event.getScreenY());
                listener.screenClicked(point);
                window.hide();
            }
        });

        window.show();

        this.listener = listener;
    }

    public Point2D getLocation(){
        return point;
    }
}

关于JavaFx 透明窗口 - 是的,请。鼠标透明 - 不,谢谢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23642238/

相关文章:

java - 如何在java swing中将组件放在图像上?

java - 如何将 Canvas 绘图转换为图像然后在屏幕上拖动它?

javascript - 使悬停菜单适用于移动设备的最佳实践方法是什么?

java - 防止 Swing GUI 在调用既访问 Swing 组件又耗时的方法时无响应

java - 与泛型类型进行比较

text - JavaFx 2.x : How to write text on a chart?

css - 在 Eclipse 中抑制 JavaFX CSS 错误?

java - 使用 javafx 从 webview 获取打印

python - 在python中生成鼠标键盘组合事件

c++ - 声明在 Qt 中发生鼠标事件时调用的函数