web-dev-qa-db-fra.com

Effet JavaFX sur le fond

J'utilise this pour créer une application JavaFX2 (Java7) sur le thème iOS avec un effet de verre dépoli. Le problème est que ce code utilise son effet sur un ImageView. Je voudrais qu'il utilise son effet sur tout ce qui est derrière la fenêtre, comme ceci:

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

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

Cela peut être important: j'utilise une version modifiée de Undecorator .

23
Taconut

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
jewelsea

L'effet visuel souhaité pour la décoration de fenêtre dépend du système d'exploitation ne peut être obtenu qu'à l'aide des API fournies par le système d'exploitation. Et donc a été éliminé par StageStyle.TRANSPARENT ci-dessous.

Pour le contenu JavaFX lui-même, vous pouvez contrôler les éléments visuels de la hiérarchie stage > scene > root pane. La scène et la scène ne supportent pas (et ne visent pas) les styles avancés, elles ont donc été éliminées en définissant comme transparent en 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 d'ombre portée ne fonctionne pas bien avec la valeur alpha de la couleur d'arrière-plan. Vous pouvez l'observer en changeant la couleur de l'ombre en un autre contraste.

Sortie:
enter image description here

10
Uluk Biy

L'opacité est une propriété de Node, qui est la classe parent en JavaFX pour les éléments affichés à l'écran. http://docs.Oracle.com/javafx/2/api/javafx/scene/Node.html#opacityProperty

Ainsi, vous pouvez simplement définir l'opacité sur l'objet que vous voulez faire disparaître. Vous devez ensuite ajouter une sorte de moyen de changer l'opacité sur l'objet souhaité. L'utilisation du curseur de votre image est un moyen, mais il y en a d'autres.

Les ombres portées peuvent être réalisées à l'aide de 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 un niveau élevé, mais s'il y a des questions de suivi dans les commentaires, je peux vous aider à y répondre.

0
Jose Martinez