JavaFX中的磨砂玻璃效果?

我正在制作一个以iOS7为主题的JavaFX2 / FXML项目,我想知道如何让Rectangle对象具有类似iOS7的磨砂玻璃效果。

我也喜欢它有一个小阴影。 这很棘手,因为您可能能够看到半透明对象后面的阴影。 我只是希望它出现在边缘。

这可能吗? 这是一张显示所需效果的图片(不包括小阴影):

我希望它看起来像这样

更新: 这是问题的延续。 这看起来很神奇:D。

样品溶液

霜

运行下面的程序并向上滚动或向上滑动以显示玻璃窗格。

该计划的目的只是为了对所涉及的技术进行抽样,而不是充当霜冻效应的通用库。

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

来源图片

将此图像与Java源并行保存为名为ios-screenshot.png的文件,并让构建系统将其复制到目标目录,以获取构建的二进制输出。

IOS-截图

其他问题的答案

“JDK 8”,这恰好是这个要求吗?

上面的示例代码是针对JDK 8编写的。通过使用匿名内部类替换lambda调用将其移植回JDK 7非常简单。

一般来说,Java 7对于JavaFX的工作非常过时。 我建议您尽早升级以使用Java 8最低版本。

用参数启动你的Panes

大多数父节点的更方便的构造函数是Java 8特性 。 您可以轻松转换Java 8格式:

  StackPane stack = new StackPane(child1, child2); 

到Java 7:

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

如果桌面位于冷冻窗格后面,这会有效吗?

不是直接的,你可以为此创建一个新问题。

更新:相关问题

用户创建: 对背景的JavaFX效果允许将磨砂效果应用于桌面背景上的窗口。

另一个用户创建: 如何创建仅在边框上具有阴影的JavaFX透明舞台? 在此窗口周围应用光晕阴影效果。