JavaFX-Effekt im Hintergrund

Lesezeit: 7 Minuten

JavaFX Effekt im Hintergrund
Taconut

Ich verwende dies, um eine JavaFX2 (Java7)-Anwendung im iOS-Design mit einem Milchglaseffekt zu erstellen. Das Problem besteht darin, dass dieser Code seine Wirkung auf eine ImageView verwendet. Ich möchte, dass es seine Wirkung auf alles ausübt, was sich hinter dem Fenster befindet, wie folgt:

JavaFX Effekt im Hintergrund

Gibt es das trotzdem? Ich hätte auch gerne den kleinen Schlagschatteneffekt, den Sie um das obige Bild herum sehen.

Um es klar zu sagen, ich möchte nicht diesen Schieberegler oder so, nur den Effekt, durch das Fenster sehen zu können und diesen leichten Schatten an den Rändern zu haben. Ich möchte jedoch diesen iOS7-ähnlichen Effekt anstelle von Aero verwenden.

Dies könnte wichtig sein: Ich verwende eine modifizierte Version von Undekorierer.

1641583756 318 JavaFX Effekt im Hintergrund
Juwelensee

eisig

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.nnDrag to movennDouble 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

  • Milchglaseffekt in JavaFX?
  • Wie erstelle ich eine transparente JavaFX-Bühne mit Schatten nur am Rand?

  • Lol. du hast es wieder getan 😀 Gut, dass ich dir ein paar Sekunden vor dem Ende des Kopfgeldes zugesprochen habe. Ich war am Ausrasten da draußen.

    – Taconut

    9. Apr. ’14 um 14:12

  • Hallo! Ich habe es so gemacht, dass Sie jeden Knoten auf einem FrostyPane laden können und die Unschärfe deaktiviert haben, wenn das Fenster nicht im Fokus war (um es immer konsistent zu machen). Ich habe ein paar Fragen: 1. Ich habe den Code entfernt, der alles für 50 ms anhält, und es funktioniert immer noch einwandfrei. Gibt es etwas, das ich vermisse? 2. Durch Ziehen des Fensters werden alle Funktionen neu gestartet, die ich ausgeführt habe. Mein Begrüßungsbildschirm wird beispielsweise neu gestartet, wenn ich das Fenster bewege. Gibt es eine Möglichkeit, dies zu umgehen? Gibt es auch eine Möglichkeit, die Größenänderung einfach zu implementieren? Ich glaube, ich kann damit umgehen, aber ich wollte nur wissen, ob Sie irgendwelche Abkürzungen kennen.

    – Taconut

    10. Apr. ’14 um 22:49

  • 1

    Wenn sich der Hintergrund ändert, wird der Glaseffekt leider nicht neu gezeichnet. Ansonsten sieht super aus.

    – dejuknow

    26. August ’14 um 5:04

  • @jewelsea line 69 “Der Roboter des Untergangs schlägt zu!” xaxaxaxa +100

    – GOXR3PLUS

    9. Juni ’16 um 16:12


1641583756 820 JavaFX Effekt im Hintergrund
Uluk Biy

Der visuelle Effekt, den Sie für die betriebssystemabhängige Fensterdekoration wünschen, kann nur durch die APIs erreicht werden, die das Betriebssystem bereitstellt. Und so wurde eliminiert von StageStyle.TRANSPARENT unter.

Für JavaFX-Inhalte selbst können Sie die Visuals der stage > scene > root pane Hierarchie. Bühne und Szene unterstützen keine erweiterten Stile (und zielen auch nicht darauf ab), daher wurden sie unten durch die Einstellung als transparent eliminiert.

@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 Schlagschatteneffekt spielt jedoch nicht gut mit dem Alpha-Wert der Hintergrundfarbe zusammen. Sie können dies beobachten, indem Sie die Farbe des Schattens in eine andere Kontrastfarbe ändern.

Ausgabe:
Bildbeschreibung hier eingeben

  • Auch diese Antwort ist richtig. Wie sage ich zu beiden ja…?

    – Taconut

    9. Apr. ’14 um 15:33

1641583757 661 JavaFX Effekt im Hintergrund
jdub1581

Um die Antwort von Jewlsea zu erweitern .. Und das obige Beispiel NUR mit JavaFX verwenden ..

Obwohl die Klassen keine öffentliche API sind, wird der AWT-Stack vollständig vermieden. Hier ist ein nicht öffentlich 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 hinzugefügten Schlagschatten:

    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

Die Deckkraft ist eine Eigenschaft von Node, der Elternklasse in JavaFX für Dinge, die auf dem Bildschirm angezeigt werden. http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html#opacityProperty

Sie können also einfach die Deckkraft des Objekts einstellen, 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 auch 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 es in den Kommentaren Folgefragen gibt, kann ich helfen, sie zu beantworten.

.

178860cookie-checkJavaFX-Effekt im Hintergrund

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy