JavaFX中的磨砂玻璃效果? [英] Frosted Glass Effect in JavaFX?

查看:197
本文介绍了JavaFX中的磨砂玻璃效果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



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





更新:



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



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

  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;

//在滚动或向上滑动时滑动霜窗格;将其滑出滚动或向下滑动。
公共类Frosty扩展Application {

private static final double W = 330;
私有静态最终双H = 590;

private static final double BLUR_AMOUNT = 60;
private static final持续时间SLIDE_DURATION = Duration.seconds(0.4);

私有静态最终双倍UPPER_SLIDE_POSITION = 100;

private static final效果frostEffect =
新BoxBlur(BLUR_AMOUNT,BLUR_AMOUNT,3);

@Override public void start(阶段阶段){
DoubleProperty y = new SimpleDoubleProperty(H);

节点background = createBackground();
节点霜=冻结(背景,y);
节点内容= createContent();
content.setVisible(false);

场景场景=新场景(
新StackPane(
背景,
霜冻,
含量

);

stage.setScene(场景);
stage.show();

addSlideHandlers(y,content,scene);
}

//创建一个要冻结的后台节点。
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);

返回背景;
}

//创建一些要在冷冻玻璃面板上显示的内容。
private Label createContent(){
Label label = new Label(覆盖的文本清晰,下面的背景是冷淡的。);

label.setStyle( - fx-font-size:25px; -fx-text-fill:midnightblue;);
label.setEffect(new Glow());
label.setMaxWidth(W - 20);
label.setWrapText(true);

返回标签;
}

//添加处理程序以将玻璃面板滑入和滑出。
private void addSlideHandlers(DoubleProperty y,Node content,Scene scene){
Timeline slideIn = new Timeline(
new KeyFrame(
SLIDE_DURATION,
new KeyValue($ b) $ by,
UPPER_SLIDE_POSITION


);

slideIn.setOnFinished(e - > content.setVisible(true));

时间轴slideOut =新时间轴(
新KeyFrame(
SLIDE_DURATION,
新KeyValue(
y,
H


);

scene.setOnSwipeUp(e - > {
slideOut.stop();
slideIn.play();
});

scene.setOnSwipeDown(e - > {
slideIn.stop();
slideOut.play();
content.setVisible(false);
});

//如果您有触摸屏,则无需滚动处理程序。
scene.setOnScroll((ScrollEvent e) - > {
if(e.getDeltaY()< 0){
slideOut.stop();
slideIn.play( );
} else {
slideIn.stop();
slideOut.play();
content.setVisible(false);
}
} );
}

//从后台节点创建一个严格的窗格。
private StackPane freeze(Node background,DoubleProperty y){
Image frostImage = background.snapshot(
new SnapshotParameters(),
null
);
ImageView frost = new ImageView(frostImage);

矩形填充=新矩形(0,0,W,H);
filler.setFill(Color.AZURE);

Pane frostPane =新窗格(霜冻);
frostPane.setEffect(frostEffect);

StackPane frostView = new StackPane(
填充,
frostPane
);

Rectangle clipShape = new Rectangle(0,y.get(),W,H);
frostView.setClip(clipShape);

clipShape.yProperty()。bind(y);

返回frostView;
}

public static void main(String [] args){launch(args); }
}

来源图片



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





其他问题的答案


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


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

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


使用参数启动您的窗格


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

  StackPane stack = new StackPane(child1,child2); 

到Java 7:

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




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


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



更新:相关问题



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



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


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.

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's a continuation of the issue. This is going to look amazing :D.

解决方案

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.

Answers to additional questions

"JDK 8," would that happen to be a requirement of this?

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.

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.

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:

 StackPane stack = new StackPane(child1, child2);

To 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 background to allow the frosted effect to apply to a window over a desktop background.

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中的磨砂玻璃效果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆