JavaFX 使用动画最小化和最大化未装饰的舞台

2024-04-30

我在这个问题中使用已接受的答案:JavaFX 最小化未修饰的阶段 https://stackoverflow.com/questions/26972683/javafx-minimizing-undecorated-stage正确最小化我的应用程序。

然而,不幸的是,默认的 Windows 最小化和最大化动画根本不显示(窗口只是出现然后消失)。

我知道可以使用未修饰的窗口显示动画,因为我有一个具有此行为的应用程序(PotPlayer)。

我怎样才能让动画出现在JNA 中?

EDIT:这是一个有效的 Kotlin 代码片段,可以正确最小化 JavaFX 窗口,还添加了奖励。

fun makeMinimizable(stage: Stage) {
         val user32 = User32.INSTANCE
         val hWnd = user32.FindWindow(null, stage.title)
         val oldStyle = user32.GetWindowLong(hWnd, WinUser.GWL_STYLE)
         val newStyle = oldStyle or 0x00020000 // WS_MINIMIZEBOX
         user32.SetWindowLong(hWnd, WinUser.GWL_STYLE, newStyle)
    }

经过对 Windows 动画的进一步研究,看起来可以组合出一个解决方案。这似乎更多是操作系统问题,而不仅仅是 JavaFX。

通过在 start() 中修改它,我能够使初始窗口在最小化和动画时保持未装饰状态:

    int newStyle = oldStyle | 0x00020000 | 0x00C00000;

但是,最小化并重新打开后,Windows 边框显得很奇怪。

然后,我尝试在图标化时使用 ChangeListener 来交换 Windows 样式。

stage.iconifiedProperty().addListener(new ChangeListener<Boolean>() {

        @Override
        public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
            if (t1.booleanValue() == true) {
                int newStyle = oldStyle | 0x00020000 | 0x00C00000;
                user32.SetWindowLong(hwnd, GWL_STYLE, newStyle);
            } else if (t1.booleanValue() == false) {
                int newStyle = oldStyle | 0x00020000;
                user32.SetWindowLong(hwnd, GWL_STYLE, newStyle);
            }
        }
    });

这成功地使窗口非最小化动画能够一致地正常工作,同时使(可见)舞台无边框。

一旦找到重新应用的最佳方法,我就可以使最小化动画正常工作:

    int newStyle = oldStyle | 0x00020000 | 0x00C00000;
    user32.SetWindowLong(hwnd, GWL_STYLE, newStyle);

就在舞台被图标化之前,并且边框对用户不可见。实施后,其工作方式可能与下面第一个链接中的 C# 解决方案类似。基本上,上面的 ChangeListener 的作用正好相反。

我认为我们需要另一个线程在后台监听来完成这个解决方案,等待图标化事件发生。我认为 stage.isIconified() == false 应该是事件触发时的情况,然后我们在后台线程中执行必要的任务来设置上述代码。然后,(...有点工作)changeListener 会将其重置回没有动画的非框架窗口,当取消最小化时,直到再次最小化。

有一个小错误,第一个未最小化显示的舞台底部部分被剪切和复制了一点,但在后续操作后它消失了。我们可能需要尝试将第二个十六进制更改为触发动画的其他内容,并在 ChangeListener 之外和另一个线程中设置所有内容。

我计划很快在我自己的外汇程序中完成这个工作。我还是一名学生,所以我对多线程和服务不太有经验,但我对如何去做有一个好主意,这只需要几个小时的黑客攻击。

如果您在此期间取得任何进展,请告诉我!这是一个很好的起点。目前还没有人在 Java 中解决这个问题。我正在阅读一些关于像 Steam 这样的无边界程序已经做到了这一点的讨论,但我认为没有人能够完全弄清楚他们是如何实现这一目标的,我怀疑这是通过下面的 C# hack 实现的。但是,这对于我们的目的来说已经足够了。

与解决无边框/未装饰动画有关的链接:

https://stackoverflow.com/a/31489766/7234125 https://stackoverflow.com/a/31489766/7234125

^ 我们需要实现这个答案,选项 #1,从 C# 到 Java

使用 Areo Snap、阴影、最小化动画和抖动的无边框窗口 https://stackoverflow.com/questions/16765561/borderless-window-using-areo-snap-shadow-minimize-animation-and-shake

http://pinvoke.net/default.aspx/Constants/Window%20styles.html http://pinvoke.net/default.aspx/Constants/Window%20styles.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaFX 使用动画最小化和最大化未装饰的舞台 的相关文章

随机推荐