JavaFX 中的磨砂玻璃效果?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22622034/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Frosted Glass Effect in JavaFX?
提问by Taconut
I'm making an iOS7-themed JavaFX2/FXML project and I was wondering how I could make a Rectangle object have a iOS7-like frosted glass effect.
我正在制作一个以 iOS7 为主题的 JavaFX2/FXML 项目,我想知道如何使 Rectangle 对象具有类似 iOS7 的磨砂玻璃效果。
I'd also like it to have a small shadow. This is tricky, since you might be able to see the shadow behind the semi-transparent object. I'd just like it to be present around the edges.
我也希望它有一个小阴影。这很棘手,因为您可能会看到半透明物体背后的阴影。我只是希望它出现在边缘。
Is this possible? Here's a picture showing the desired effect (not including the small drop-shadow):
这可能吗?这是一张显示所需效果的图片(不包括小阴影):
UPDATE: Here'sa continuation of the issue. This is going to look amazing :D.
更新:这是问题的延续。这看起来很棒:D。
采纳答案by jewelsea
Sample Solution
样品溶液
Run the program below and scroll or swipe up to show the glass pane.
运行下面的程序并向上滚动或滑动以显示玻璃窗格。
The purpose of the program is just to sample the techniques involved not to act as a general purpose library for the frost effect.
该程序的目的只是对所涉及的技术进行采样,而不是充当霜冻效果的通用库。
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); }
}
Source image
源图像
Save this image parallel to the Java source as a file named ios-screenshot.png
and have your build system copy it to the target directory for the binary output of the build.
将此映像与 Java 源代码并行保存为一个名为的文件,ios-screenshot.png
并让您的构建系统将其复制到目标目录以用于构建的二进制输出。
Answers to additional questions
其他问题的答案
"JDK 8," would that happen to be a requirement of this?
“JDK 8”,这会是一个要求吗?
The sample code above is written against JDK 8. Porting it back to JDK 7 by replacing the lambda calls with anonymous inner classes is pretty trivial.
上面的示例代码是针对 JDK 8 编写的。通过用匿名内部类替换 lambda 调用将其移植回 JDK 7 非常简单。
In general, Java 7 is pretty dated for JavaFX work. I advise upgrading at your earliest convenience to work with a Java 8 minimum version.
一般来说,Java 7 对于 JavaFX 工作来说已经过时了。我建议您尽早升级以使用 Java 8 最低版本。
initiating your Panes with arguments
用参数启动你的窗格
More convenient constructors for most parent nodes is a Java 8 feature. You can easily convert the Java 8 format:
对于大多数父节点来说,更方便的构造函数是Java 8 的一个特性。您可以轻松转换 Java 8 格式:
StackPane stack = new StackPane(child1, child2);
To Java 7:
到 Java 7:
StackPane stack = new StackPane();
stack.getChildren().setAll(child1, child2);
will this working if the desktop is behind a frosty pane?
如果桌面在结霜的窗格后面,这会起作用吗?
Not directly, you can create a new question for that.
不是直接的,您可以为此创建一个新问题。
Update: Related Questions
更新:相关问题
User created: JavaFX effect on backgroundto allow the frosted effect to apply to a window over a desktop background.
用户创建:背景上的JavaFX 效果,允许将磨砂效果应用于桌面背景上的窗口。
Another user created: How do I create a JavaFX transparent stage with shadows on only the border?to apply a halo shadow effect around this window.
另一个用户创建:如何创建仅在边框上带有阴影的 JavaFX 透明舞台?在此窗口周围应用光晕阴影效果。