2016-06-19 6 views
0

Je veux faire une scène transparente, comme l'image ci-dessous (Windows 7)Comment créer une scène de fenêtre transparente en utilisant javaFX?

that is windows 7 gadget window.. it looks like a fully glass

J'ai donc essayé de faire cette méthode sous forme de screencapture .. mais il était confus ...

Voici mon code, nous espérons qu'il peut expliquer mieux la question:

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

Répondre

0

la raison de l'effet que vous voyez est que le robot prend un instantané d'une partie de l'écran, y compris la fenêtre ont créé. De plus, cet instantané se produit après que les propriétés x et y de la scène ont changé mais avant que la fenêtre ne bouge réellement (et donc avant que le robot "voit" l'effet des propriétés changées). Ainsi, vous vous retrouvez avec l'image incorrecte générée.

Une solution simple est de prendre un instantané de l'écran en entier avant de montrer la scène, puis mettre à jour la fenêtre appliquée à la vue de l'image lorsque les mouvements de scène (ou la taille des changements):

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

Sur inconvénient ici est que l'image ne sera pas représentative des modifications apportées au bureau indépendamment de votre application. Une solution possible serait d'utiliser un WritableImage et de mettre à jour dynamiquement des portions de cette image non couverts par la fenêtre que la fenêtre change de position. La logique ici serait un peu difficile, mais pas trop mal.

+0

votre réponse est bonne .. mais il ne fonctionne pas comme windows 7 effet aéro .. Je veux dire lorsque vous exécutez après le programme, puis vous changez derrière l'écran .. mais aspect transparent du programme est change pas .... Oui –

+0

, c'est ce que j'ai abordé dans le dernier paragraphe. –

+0

alors pouvez-vous m'envoyer un bon code en utilisant writableImage que vous avez dit dans le dernier paragraphe ....? –