Javafx 2 如何使用javaFX创建透明窗口阶段?

Javafx 2 如何使用javaFX创建透明窗口阶段?,javafx-2,javafx-8,transparent,aero-glass,Javafx 2,Javafx 8,Transparent,Aero Glass,我想制作一个透明的舞台,如下图(Windows7) 所以我试着用屏幕截图的方法。。但这让人困惑 这是我的代码,希望它能更好地解释这个问题: import javafx.application.*; import javafx.embed.swing.SwingFXUtils; import javafx.scene.*; import javafx.scene.control.*; import javafx.scene.effect.*; import javafx.scene.image.

我想制作一个透明的舞台,如下图(Windows7)

所以我试着用屏幕截图的方法。。但这让人困惑

这是我的代码,希望它能更好地解释这个问题:

import javafx.application.*;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class Demo extends Application{
    private static final double BLUR_AMOUNT = 7;
    private static final Effect myBlur = new BoxBlur(BLUR_AMOUNT, BLUR_AMOUNT, 3);
    private static final ImageView background = new ImageView();
    private static final StackPane layout = new StackPane();

    private Button btn=new Button("hello");

    @Override 
    public void start(Stage stage) {
        layout.getChildren().addAll(background,btn);
        layout.setStyle("-fx-background-color: null");

        Scene scene = new Scene(layout,300, 300,Color.TRANSPARENT);

        stage.initStyle(StageStyle.TRANSPARENT);
        stage.setScene(scene);
        stage.show();
        stage.setX(0);
        stage.setY(0);

        background.setImage(copyBackground(stage));
        background.setEffect(myBlur);

        makeDraggable(stage);
    }

    private static class Delta {
        double x,y;
    }

    public void makeDraggable(final Stage stage) {
        final Delta dragDelta = new Delta();
        btn.setOnMousePressed(mouseEvent -> {
            dragDelta.x = stage.getX() - mouseEvent.getScreenX();
            dragDelta.y = stage.getY() - mouseEvent.getScreenY();    
        });

        btn.setOnMouseDragged(mouseEvent -> {
            stage.setX(mouseEvent.getScreenX() + dragDelta.x);
            stage.setY(mouseEvent.getScreenY() + dragDelta.y);
            btn.setOpacity(0.0);
            background.setImage(copyBackground(stage));
        });

         btn.setOnMouseReleased(mouseEvent -> {
            btn.setOpacity(1.0);
        });
    }

    private Image copyBackground(Stage stage) {
        final int X = (int) stage.getX();
        final int Y = (int) stage.getY();
        final int W = (int) stage.getWidth();
        final int H = (int) stage.getHeight();

        try {
            java.awt.Robot robot = new java.awt.Robot();
            java.awt.image.BufferedImage image = robot.createScreenCapture(new java.awt.Rectangle(X, Y, W, H));

            return SwingFXUtils.toFXImage(image, null);
        } catch (java.awt.AWTException e) {
            System.out.println("The robot of doom strikes!");
            return null;
        }
    }

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

您看到这种效果的原因是机器人正在拍摄屏幕的一部分快照,包括您创建的窗口。此外,此快照发生在舞台的
x
y
属性更改之后,但在窗口实际移动之前(因此在机器人“看到”更改属性的效果之前)。因此,最终生成的图像不正确

一个简单的修复方法是在显示舞台之前快照整个屏幕,然后在舞台移动(或更改大小)时更新应用于图像视图的视口:


这里的一个缺点是,图像不能代表桌面上独立于应用程序发生的任何更改。一种可能的解决方法是使用
WritableImage
,并在窗口改变位置时动态更新窗口未覆盖的部分图像。这里的逻辑可能有点复杂,但也不太糟糕。

你的答案很好。。但它的工作原理与Windows7的aero效果不同。。我的意思是当你运行完程序后,你会在屏幕后面改变。。但是程序透明的外观并没有改变……是的,这就是我在最后一段中提到的。那么你能用你在最后一段中提到的writableImage给我发一个正确的代码吗。。。。?
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.BoxBlur;
import javafx.scene.effect.Effect;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class Demo extends Application{
    private static final double BLUR_AMOUNT = 7;
    private static final Effect myBlur = new BoxBlur(BLUR_AMOUNT, BLUR_AMOUNT, 3);
    private static final ImageView background = new ImageView();
    private static final StackPane layout = new StackPane();

    private Button btn=new Button("hello");

    @Override 
    public void start(Stage stage) {
        layout.getChildren().addAll(background,btn);
        layout.setStyle("-fx-background-color: null");

        Scene scene = new Scene(layout,300, 300,Color.TRANSPARENT);

        stage.initStyle(StageStyle.TRANSPARENT);
        stage.setScene(scene);
        stage.show();
        stage.setX(0);
        stage.setY(0);

        background.setImage(copyBackground(stage));
        
        background.viewportProperty().bind(Bindings.createObjectBinding(() -> 
            new Rectangle2D(stage.getX(), stage.getY(), stage.getWidth(), stage.getHeight()), 
            stage.xProperty(), stage.yProperty(), stage.widthProperty(), stage.heightProperty()));
        
        background.setEffect(myBlur);

        makeDraggable(stage);
    }

    private static class Delta {
        double x,y;
    }

    public void makeDraggable(final Stage stage) {
        final Delta dragDelta = new Delta();
        btn.setOnMousePressed(mouseEvent -> {
            dragDelta.x = stage.getX() - mouseEvent.getScreenX();
            dragDelta.y = stage.getY() - mouseEvent.getScreenY();    
        });

        btn.setOnMouseDragged(mouseEvent -> {
            stage.setX(mouseEvent.getScreenX() + dragDelta.x);
            stage.setY(mouseEvent.getScreenY() + dragDelta.y);
            btn.setOpacity(0.0);
//            background.setImage(copyBackground(stage));
        });

         btn.setOnMouseReleased(mouseEvent -> {
            btn.setOpacity(1.0);
        });
    }

    private Image copyBackground(Stage stage) {
        
        Rectangle2D screen = Screen.getPrimary().getBounds() ;
        
        final int X = (int) screen.getMinX();
        final int Y = (int) screen.getMinX();
        final int W = (int) screen.getWidth();
        final int H = (int) screen.getHeight();

        try {
            java.awt.Robot robot = new java.awt.Robot();
            java.awt.image.BufferedImage image = robot.createScreenCapture(new java.awt.Rectangle(X, Y, W, H));

            return SwingFXUtils.toFXImage(image, null);
        } catch (java.awt.AWTException e) {
            System.out.println("The robot of doom strikes!");
            return null;
        }
    }

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