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:
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.
Juwelensee
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
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:
Auch diese Antwort ist richtig. Wie sage ich zu beiden ja…?
– Taconut
9. Apr. ’14 um 15:33
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:
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.