Effet verre givré à JavaFX?

je fais un projet JavaFX2/FXML sur le thème de iOS7 et je me demandais comment je pouvais faire un objet Rectangle avec un effet de verre givré de type iOS7.

j'aimerais aussi avoir une petite ombre. C'est délicat, car vous pourriez être en mesure de voir l'ombre derrière les objets semi-transparents. J'aimerais juste qu'il soit présent sur les bords.

est-ce possible? Voici une image montrant l'effet désiré (sans compter le petit drop-shadow):

I'd like it to look like this

mise à JOUR: Voici une continuation de la question. Ça va être génial :D.

12
demandé sur Community 2014-03-25 02:38:14

1 réponses

La Solution De L'Échantillon

frost

exécutez le programme ci-dessous et faites défiler ou glisser vers le haut pour montrer la vitre.

le but du programme est juste d'échantillonner les techniques impliquées pour ne pas agir comme une bibliothèque à usage général pour l'effet de gel.

import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.geometry.Rectangle2D;
import javafx.scene.*;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

// slides a frost pane in on scroll or swipe up; slides it out on scroll or swipe down.
public class Frosty extends Application {

    private static final double W = 330;
    private static final double H = 590;

    private static final double BLUR_AMOUNT = 60;
    private static final Duration SLIDE_DURATION = Duration.seconds(0.4);

    private static final double UPPER_SLIDE_POSITION = 100;

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

    @Override public void start(Stage stage) {
        DoubleProperty y = new SimpleDoubleProperty(H);

        Node background = createBackground();
        Node frost      = freeze(background, y);
        Node content    = createContent();
        content.setVisible(false);

        Scene scene = new Scene(
                new StackPane(
                        background,
                        frost,
                        content
                )
        );

        stage.setScene(scene);
        stage.show();

        addSlideHandlers(y, content, scene);
    }

    // create a background node to be frozen over.
    private Node createBackground() {
        Image backgroundImage = new Image(
                getClass().getResourceAsStream("ios-screenshot.png")
        );
        ImageView background = new ImageView(backgroundImage);
        Rectangle2D viewport = new Rectangle2D(0, 0, W, H);
        background.setViewport(viewport);

        return background;
    }

    // create some content to be displayed on top of the frozen glass panel.
    private Label createContent() {
        Label label = new Label("The overlaid text is clear and the background below is frosty.");

        label.setStyle("-fx-font-size: 25px; -fx-text-fill: midnightblue;");
        label.setEffect(new Glow());
        label.setMaxWidth(W - 20);
        label.setWrapText(true);

        return label;
    }

    // add handlers to slide the glass panel in and out.
    private void addSlideHandlers(DoubleProperty y, Node content, Scene scene) {
        Timeline slideIn = new Timeline(
                new KeyFrame(
                        SLIDE_DURATION,
                        new KeyValue(
                                y,
                                UPPER_SLIDE_POSITION
                        )
                )
        );

        slideIn.setOnFinished(e -> content.setVisible(true));

        Timeline slideOut = new Timeline(
                new KeyFrame(
                        SLIDE_DURATION,
                        new KeyValue(
                                y,
                                H
                        )
                )
        );

        scene.setOnSwipeUp(e -> {
            slideOut.stop();
            slideIn.play();
        });

        scene.setOnSwipeDown(e -> {
            slideIn.stop();
            slideOut.play();
            content.setVisible(false);
        });

        // scroll handler isn't necessary if you have a touch screen.
        scene.setOnScroll((ScrollEvent e) -> {
            if (e.getDeltaY() < 0) {
                slideOut.stop();
                slideIn.play();
            } else {
                slideIn.stop();
                slideOut.play();
                content.setVisible(false);
            }
        });
    }

    // create a frosty pane from a background node.
    private StackPane freeze(Node background, DoubleProperty y) {
        Image frostImage = background.snapshot(
                new SnapshotParameters(),
                null
        );
        ImageView frost = new ImageView(frostImage);

        Rectangle filler = new Rectangle(0, 0, W, H);
        filler.setFill(Color.AZURE);

        Pane frostPane = new Pane(frost);
        frostPane.setEffect(frostEffect);

        StackPane frostView = new StackPane(
                filler,
                frostPane
        );

        Rectangle clipShape = new Rectangle(0, y.get(), W, H);
        frostView.setClip(clipShape);

        clipShape.yProperty().bind(y);

        return frostView;
    }

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

Image Source

enregistrez cette image parallèlement à la source Java sous la forme d'un fichier nommé ios-screenshot.png et demandez à votre système de compilation de la Copier dans le répertoire cible pour la sortie binaire de la compilation.

ios-screenshot

réponses aux questions supplémentaires

"JDK 8," est-ce que cela serait une condition de ceci?

le exemple de code ci-dessus est écrit contre JDK 8. Le faire revenir à JDK 7 en remplaçant les appels lambda par des classes internes anonymes est assez banal.

en général, Java 7 est assez daté pour le travail JavaFX. Je vous conseille de mettre à niveau dès que possible pour travailler avec une version Java 8 minimum.

initier vos Volets, avec des arguments

les constructeurs plus pratiques pour la plupart des noeuds parents est un Java 8 fonction . Vous pouvez facilement convertir le format Java 8:

 StackPane stack = new StackPane(child1, child2);

To Java 7:

 StackPane stack = new StackPane();
 stack.getChildren().setAll(child1, child2);

cette travail si le bureau est derrière glacial volet?

Pas directement, vous pouvez créer une nouvelle question.

Mise À Jour: Questions Connexes

créé par l'Utilisateur: JavaFX effet sur le fond pour permettre à l'effet givré de s'appliquer à une fenêtre sur un fond de bureau.

un autre utilisateur a créé: comment créer une scène transparente JavaFX avec des ombres uniquement sur la frontière? pour appliquer un effet d'ombre halo autour de cette fenêtre.

18
répondu jewelsea 2017-05-23 11:53:02