【问题标题】:JavaFX: Can't show opacity transitions on transparent stages?JavaFX:不能在透明阶段显示不透明过渡?
【发布时间】:2015-10-13 01:41:54
【问题描述】:

我要做的是在带有阴影效果的透明舞台(弹出通知)上显示淡入/淡出过渡效果。

我创建了一个透明场景,将 StackPane fx:id="rootNode" 设置为 -fx-background-color: transparent,并在 StackPane 内包裹了一个带有阴影效果的 AnchorPane。接下来,我用那个场景设置我的透明舞台。

@FXML private StackPane rootNode;

Parent rootNode = FXMLLoader.load(getClass().getResource("notification.fxml"));
Scene scene = new Scene(rootNode, Color.TRANSPARENT);

Stage stage = new Stage();
stage.initStyle(StageStyle.TRANSPARENT);
stage.setScene(scene);

到目前为止一切顺利。我设法得到了这个带有漂亮阴影效果的透明舞台。

注意:下图显示了我的桌面上带有阴影效果的透明舞台,它具有青色。


但是现在,由于我添加了一些过渡效果来逐渐淡入和淡出Stage(当用户点击“x”时),Stage 几乎没有显示出来。过渡效果之类的东西在执行过程中停止(我将不透明度从 0.0 转换为 1.0)。

您可以在下面的任务栏中看到它,因为第二个 java 窗口就是那个阶段。


如果我将光标放在“x”按钮上,它就会显示出来。这意味着(我想)播放了过渡,但舞台(不知何故)没有显示或透明,直到某些东西抓住了它的焦点。

我试过了

setting stage.toFront(); 
stage.requestFocus(); 
stage.setAlwaysOnTop(true);

没有成功。

当我在Stage 上更改StageStyle.UNDECORATED 时,会显示带有过渡的舞台,但它周围有令人讨厌的白色背景,这是意料之中的。

您能提供一些帮助吗?我不明白为什么会发生这种情况或如何找到可能的解决方案。

我的设置是:

  • Windows 7 x64 专业版

  • Java(TM) SE 运行时环境(内部版本 1.8.0_45-b15)


--- 更新 ---

经过一些测试,我得出结论,StageStyle.TRANSPARENT 阶段和 transition opacity 效果之间可能存在“不兼容”?


我的转换代码是:

public class FadeTransition {

    private final Timeline showTransition, dismissTransition;
    private final NotificationStage stage;

    public FadeTransition(NotificationStage customStage) {
        this.stage = customStage;

        showTransition = setupShowTransition();
        dismissTransition = setupDismissTransition();
    }

    private Timeline setupShowTransition() {
        Timeline tl = new Timeline();

        // Set opacity to 0.0 instantly
        KeyValue kvOpacity = new KeyValue(stage.opacityProperty(), 0.0);
        KeyFrame frame1 = new KeyFrame(Duration.ZERO, kvOpacity);

        // Sets opacity to 1.0 gradually over 500 milliseconds.
        KeyValue kvOpacity2 = new KeyValue(stage.opacityProperty(), 1.0);
        KeyFrame frame2 = new KeyFrame(Duration.millis(500), kvOpacity2);

        tl.getKeyFrames().addAll(frame1, frame2);

        //Action to be performed when the transition has finished
        tl.setOnFinished(e -> notificationIsShowing = true);

        return tl;
    }

    private Timeline setupDismissTransition() {
        Timeline tl = new Timeline();

        // At this stage the opacity is already at 1.0

        // Lower the opacity to 0.0 within 1000 milliseconds
        KeyValue kv1 = new KeyValue(stage.opacityProperty(), 0.0);
        KeyFrame kf1 = new KeyFrame(Duration.millis(1000), kv1);

        tl.getKeyFrames().addAll(kf1);

        //Action to be performed when the transition has finished
        tl.setOnFinished(e -> {
            notificationIsShowing = false;
            stage.close();
            stage.setLocation(stage.getAnchorLocation());
        });

        return tl;
    }

    public void playShowTransition() {
        showTransition.play();
    }

    public void playDismissAnimation() {
        dismissTransition.play();
    }

    ... ... ...
}

【问题讨论】:

  • 虽然我不太清楚为什么新版本的外观会发生这种变化,但您可以通过从 hbox 的样式中删除 -fx-background-insets-fx-border-insets 来解决此问题。
  • @ItachiUchiha 我更改了整个代码。请看一下。感谢您的回复。
  • 一个问题:这是来自 ControlsFX 的控件吗?
  • @PeterPenzov 不,不是。这是我的自定义阶段。
  • 如果这是一个开源应用程序,您可以分享代码吗?我对这个解决方案是如何实现的很感兴趣。

标签: javafx shadow stage


【解决方案1】:

另一个人 here 遇到了完全相同的问题,并将其声明为 JavaFX 错误。

解决方法是构建自定义Interpolator (bugFixInterpolator) 来重新绘制场景。

这是部分代码,贴在上面的链接中:

Interpolator bugFixInterpolator = new Interpolator() {
            @Override
            protected double curve(double t) {
                Paint fill = scene.getFill();
                scene.setFill(Color.RED);
                scene.setFill(fill);
                return t;
            }

            @Override
            public String toString() {
                return "Interpolator.LINEAR";
            }
        };

        Timeline t = new Timeline(new KeyFrame(Duration.millis(0),
                new KeyValue(stage.opacityProperty(), 1, bugFixInterpolator)),
                new KeyFrame(Duration.millis(500), new KeyValue(stage
                        .opacityProperty(), 0, bugFixInterpolator)));
        t.setAutoReverse(true);
        t.setCycleCount(Timeline.INDEFINITE);
        t.playFromStart();

【讨论】:

    猜你喜欢
    • 2021-01-08
    • 2021-07-26
    • 2011-06-22
    • 2014-05-25
    • 2020-05-29
    • 2015-11-08
    • 1970-01-01
    • 2014-07-11
    • 2017-06-27
    相关资源
    最近更新 更多