it-swarm.com.de

JavaFX-Effekt auf den Hintergrund

Ich verwende this , um eine iOS-gestützte JavaFX2 (Java7) -Anwendung mit einem Mattglaseffekt zu erstellen. Das Problem ist, dass dieser Code seine Auswirkungen auf eine ImageView verwendet. Ich möchte, dass es seine Wirkung auf das, was sich hinter dem Fenster befindet, wie folgt auswirkt:

Gibt es das überhaupt zu tun? Ich möchte auch diesen kleinen Schatteneffekt, den Sie um das obige Bild sehen.

Um klar zu sein, ich möchte diesen Schieberegler oder etwas nicht, nur den Effekt, durch das Fenster sehen zu können und einen leichten Schatten an den Kanten zu haben. Ich möchte jedoch diesen iOS7-ish-Effekt anstelle von Aero verwenden.

Das könnte wichtig sein: Ich verwende eine modifizierte Version von 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);
    }
}  

Verwandte Fragen

20
jewelsea

Der visuelle Effekt, den Sie für die Betriebssystemabhängige Fensterdekoration wünschen, kann nur durch die APIs des Betriebssystems erzielt werden. Und so wurde durch StageStyle.TRANSPARENT unten beseitigt.

Für JavaFX-Inhalte selbst können Sie die Anzeige der stage > scene > root pane-Hierarchie steuern. Bühne und Szene unterstützen erweiterte Stylings nicht (und sollten nicht darauf ausgerichtet sein).

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

Der Schatteneffekt spielt jedoch nicht gut mit dem Alpha-Wert der Hintergrundfarbe. Sie können es beobachten, indem Sie die Farbe des Schattens in einen anderen Kontrast ändern.

Ausgabe:
enter image description here

10
Uluk Biy

So erweitern Sie die Antwort von Jewlsea: Verwenden Sie das obige Beispiel NUR mit JavaFX.

Obwohl die Klassen keine öffentliche API sind, wird der AWT-Stack vollständig vermieden. Hier ist ein nicht öffentliches Beispiel:

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

Ergebnisse mit einem kleinen Schlagschatten hinzugefügt:

    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
jdub1581

Die Deckkraft ist eine Eigenschaft von Node, der übergeordneten Klasse in JavaFX für auf dem Bildschirm angezeigte Dinge. http://docs.Oracle.com/javafx/2/api/javafx/scene/Node.html#opacityProperty

Sie können also einfach die Deckkraft für das Objekt festlegen, das ausgeblendet werden soll. Sie müssen dann eine Möglichkeit hinzufügen, um die Deckkraft des gewünschten Objekts zu ändern. Die Verwendung des Schiebereglers aus Ihrem Bild ist eine Möglichkeit, aber es gibt andere.

Schlagschatten können mit dem DropShadow-Effekt erstellt werden ... http://docs.Oracle.com/javafx/2/api/javafx/scene/effect/DropShadow.html . Ich habe es noch nie benutzt. Dies ist ein wenig hoch, aber wenn in den Kommentaren weitere Fragen stehen, kann ich Ihnen helfen, sie zu beantworten.

0
Jose Martinez