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

时间:2014-05-13 21:53:15

标签: java javafx-2 mouseevent transparency

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

我在矩形和根窗格上使用了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!例。当我将鼠标悬停在按钮上时,点击按钮或只是单击“直通”并将焦点放在底层窗口(在我的情况下通常是eclipse)的概率大约为50:50。会爱上你的想法。

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

1 个答案:

答案 0 :(得分:2)

检查您的进口

你正在使用某种奇怪的设置来混合AWT / Swing类和JavaFX类,实际上并不建议(并且在你使用的组合和方式中根本不起作用)。在JavaFX程序中要小心,不要导入任何java.awt.*javax.swing.*类,除非你真的知道在为两个不同的工具包混合代码时你在做什么。

示例解决方案

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

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