Effet JavaFX sur le fond

j'utilise ce pour réaliser une application JavaFX2 (Java7) sur le thème de l'iOS avec un effet de verre givré. Le problème est que ce code utilise son effet sur une ImageView. Je voudrais qu'il utilise son effet sur ce qui est derrière la fenêtre, comme ceci:

y a-t-il un moyen de faire ça? J'aimerais aussi que petit effet d'ombre portée que vous voyez autour de l'image ci-dessus.

pour être clair, je Je ne veux pas de ce curseur ou quoi que ce soit, juste l'effet d'être capable de voir à travers la fenêtre et d'avoir cette ombre légère autour des bords. Je veux utiliser cet effet iOS7-ish au lieu d'aero, cependant.

cela pourrait être important: j'utilise une version modifiée de Undécorateur .

23
demandé sur Community 2014-03-26 18:13:30

4 réponses

frosty

import javafx.animation.*;
import javafx.application.*;
import javafx.beans.property.*;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.Label;
import javafx.scene.effect.*;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.image.*;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;

public class FrostyTech extends Application {

    private static final double BLUR_AMOUNT = 10;

    private static final Effect frostEffect =
        new BoxBlur(BLUR_AMOUNT, BLUR_AMOUNT, 3);

    private static final ImageView background = new ImageView();
    private static final StackPane layout = new StackPane();

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

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

        Platform.setImplicitExit(false);

        scene.setOnMouseClicked(event -> {
                if (event.getClickCount() == 2) Platform.exit();
        });
        makeSmoke(stage);

        stage.initStyle(StageStyle.TRANSPARENT);
        stage.setScene(scene);
        stage.show();

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

        makeDraggable(stage, layout);
    }

    // copy a background node to be frozen over.
    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!");
            e.printStackTrace();

            return null;
        }
    }

    // create some content to be displayed on top of the frozen glass panel.
    private Label createContent() {
        Label label = new Label("Create a new question for drop shadow effects.\n\nDrag to move\n\nDouble click to close");
        label.setPadding(new Insets(10));

        label.setStyle("-fx-font-size: 15px; -fx-text-fill: green;");
        label.setMaxWidth(250);
        label.setWrapText(true);

        return label;
    }

    // makes a stage draggable using a given node.
    public void makeDraggable(final Stage stage, final Node byNode) {
        final Delta dragDelta = new Delta();
        byNode.setOnMousePressed(mouseEvent -> {
            // record a delta distance for the drag and drop operation.
            dragDelta.x = stage.getX() - mouseEvent.getScreenX();
            dragDelta.y = stage.getY() - mouseEvent.getScreenY();
            byNode.setCursor(Cursor.MOVE);
        });
        final BooleanProperty inDrag = new SimpleBooleanProperty(false);

        byNode.setOnMouseReleased(mouseEvent -> {
            byNode.setCursor(Cursor.HAND);

            if (inDrag.get()) {
                stage.hide();

                Timeline pause = new Timeline(new KeyFrame(Duration.millis(50), event -> {
                    background.setImage(copyBackground(stage));
                    layout.getChildren().set(
                            0,
                            background
                    );
                    stage.show();
                }));
                pause.play();
            }

            inDrag.set(false);
        });
        byNode.setOnMouseDragged(mouseEvent -> {
            stage.setX(mouseEvent.getScreenX() + dragDelta.x);
            stage.setY(mouseEvent.getScreenY() + dragDelta.y);

            layout.getChildren().set(
                    0,
                    makeSmoke(stage)
            );

            inDrag.set(true);
        });
        byNode.setOnMouseEntered(mouseEvent -> {
            if (!mouseEvent.isPrimaryButtonDown()) {
                byNode.setCursor(Cursor.HAND);
            }
        });
        byNode.setOnMouseExited(mouseEvent -> {
            if (!mouseEvent.isPrimaryButtonDown()) {
                byNode.setCursor(Cursor.DEFAULT);
            }
        });
    }

    private javafx.scene.shape.Rectangle makeSmoke(Stage stage) {
        return new javafx.scene.shape.Rectangle(
                stage.getWidth(),
                stage.getHeight(),
                Color.WHITESMOKE.deriveColor(
                        0, 1, 1, 0.08
                )
        );
    }

    /** records relative x and y co-ordinates. */
    private static class Delta {
        double x, y;
    }

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

Questions Connexes

20
répondu jewelsea 2017-05-23 11:54:53

l'effet visuel que vous voulez pour la décoration de fenêtre dépendante de L'OS, ne peut être atteint que par les API que L'OS fournit. Et a donc été éliminé par StageStyle.TRANSPARENT ci-dessous.

pour le contenu JavaFX lui-même, vous pouvez contrôler les visuels de la hiérarchie stage > scene > root pane . La scène et la scène ne soutiennent pas (et ne visent pas) les stylings avancés ainsi ont été éliminés en mettant comme transparent ci-dessous.

@Override
public void start(Stage primaryStage) {
    StackPane root = new StackPane();
    root.setStyle("-fx-background-color: null;");
    root.setPadding(new Insets(10));

    DoubleProperty doubleProperty = new SimpleDoubleProperty(0);

    Region region = new Region();
    region.styleProperty().bind(Bindings
            .concat("-fx-background-radius:20; -fx-background-color: rgba(56, 176, 209, ")
            .concat(doubleProperty)
            .concat(");"));
    region.setEffect(new DropShadow(10, Color.GREY));

    Slider slider = new Slider(0, 1, .3);
    doubleProperty.bind(slider.valueProperty());

    root.getChildren().addAll(region, slider);

    primaryStage.initStyle(StageStyle.TRANSPARENT);
    Scene scene = new Scene(root, 300, 250);
    scene.setFill(Color.TRANSPARENT);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
}

cependant l'effet drop shadow ne ne joue pas bien avec la valeur alpha de la couleur de fond. Vous pourrez l'observer en changeant l'ombre de la couleur de contraste.

sortie:

enter image description here

10
répondu Uluk Biy 2014-04-09 10:46:30

pour développer la réponse de Jewlsea .. Et en utilisant L'exemple ci-dessus avec JavaFX seulement ..

bien que les classes ne soient pas des API publiques, elles évitent complètement la pile AWT. Voici un non public 151980920" exemple:

// copy a background node to be frozen over.
    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();
        final Screen screen = Screen.getPrimary();
        try {

            Robot rbt = com.sun.glass.ui.Application.GetApplication().createRobot();
            Pixels p = rbt.getScreenCapture(
                (int)screen.getBounds().getMinX(),
                (int)screen.getBounds().getMinY(), 
                (int)screen.getBounds().getWidth(), 
                (int)screen.getBounds().getHeight(), 
                true
            );

            WritableImage dskTop = new WritableImage((int)screen.getBounds().getWidth(), (int)screen.getBounds().getHeight());
            dskTop.getPixelWriter().setPixels(
                (int)screen.getBounds().getMinX(),
                (int)screen.getBounds().getMinY(),
                (int)screen.getBounds().getWidth(),
                (int)screen.getBounds().getHeight(),
                PixelFormat.getByteBgraPreInstance(),
                p.asByteBuffer(), 
                (int)(screen.getBounds().getWidth() * 4)
            );

            WritableImage image = new WritableImage(W,H);
            image.getPixelWriter().setPixels(0, 0, W, H, dskTop.getPixelReader(), X, Y);

            return image;
        } catch (Exception e) {
            System.out.println("The robot of doom strikes!");
            e.printStackTrace();

            return null;
        }
    }

résultats avec un petit dropshadow ajouté:

    DropShadow shdw = new DropShadow();
    shdw.setBlurType(BlurType.GAUSSIAN);
    shdw.setColor(Color.GAINSBORO);
    shdw.setRadius(10);
    shdw.setSpread(0.12);
    shdw.setHeight(10);
    shdw.setWidth(10);
    layout.setEffect(shdw);

fxScreenCapture

2
répondu jdub1581 2015-03-10 10:48:28

l'opacité est une propriété de Node, qui est la classe parent dans JavaFX pour les choses qui apparaissent sur l'écran. http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html#opacityProperty

donc vous pouvez simplement régler l'opacité sur l'objet que vous voulez faire disparaître. Ensuite, vous devez ajouter une sorte de moyen de changer l'opacité sur l'objet souhaité. Utiliser le curseur de votre image est une façon, mais il y en a d'autres.

Drop shadows peut être fait en utilisant L'effet DropShadow... http://docs.oracle.com/javafx/2/api/javafx/scene/effect/DropShadow.html . Je ne l'ai jamais utilisé. C'est un peu élevé, mais s'il y a des questions de suivi dans les commentaires, je peux vous aider à y répondre.

0
répondu Jose Martinez 2014-04-08 20:40:23