JavaFX 使用动画最小化和最大化未装饰的舞台
Posted
技术标签:
【中文标题】JavaFX 使用动画最小化和最大化未装饰的舞台【英文标题】:JavaFX Minimizing & Maximing undecorated stage with animations 【发布时间】:2018-06-24 09:09:43 【问题描述】:我在这个问题中使用公认的答案:JavaFX Minimizing Undecorated Stage 来正确最小化我的应用程序。
然而,不幸的是,默认的 Windows 最小化和最大化 动画 根本没有显示(窗口只是出现然后消失)。
我知道可以使用未装饰的窗口显示动画,因为我有一个具有这种行为的应用程序 (PotPlayer)。
如何使动画与 JNA 一起出现?
编辑:这是一个有效的 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)
【问题讨论】:
我刚刚在win7上测试过,它只有旧风格主题的动画。打开 aero 主题或关闭动画时,它不会动画。我可以建议的是找到你说的程序的窗口。然后让它打印出窗口样式并尝试在你的程序中设置它。 在你的代码中看起来你添加了样式 WS_BORDER 和 WS_MINIMIZEBOX 哦,是的,0x00080000 是我刚刚尝试过的,不小心把它留在了里面。我会尝试你的建议! @brian 嗯。我尝试将 oldStyle 变量设置为与 Potplayer 相同。我没有尝试解析单个样式,而只是将“oldStyle”设置为:-1764818944。 (你可以自己试试)。这实际上有效 - 窗口未装饰,并且确实出现了最小化动画,但是,一旦我恢复窗口,窗口就不再未装饰。有什么想法吗? 我刚刚用 potplayer 得到了同样的结果。还有 GWL_EXSTYLE 设置,但它们没有任何区别。 Javafx 必须做一些不同的事情,但我不知道是什么。 【参考方案1】:在对 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 之外和另一个线程中。
我计划很快在我自己的 fx 程序中完成这项工作。我还是个学生,所以我对多线程和服务的经验不是很丰富,但我对如何去做有一个好主意,只需要几个小时的时间。
如果您在此期间取得任何进展,请告诉我!这是一个很好的起点。还没有人用 Java 解决这个问题。我正在阅读一些讨论,如 Steam 这样的无边界程序已经做到了这一点,但我认为没有人能完全弄清楚他们是如何完成它的,我怀疑是通过下面的 C# hack。但是,这对于我们的目的来说已经足够了。
解决无边界/未装饰动画的链接:
https://***.com/a/31489766/7234125
^ 我们需要实现这个答案,选项 #1,从 C# 到 Java
Borderless Window Using Areo Snap, Shadow, Minimize Animation, and Shake
http://pinvoke.net/default.aspx/Constants/Window%20styles.html
【讨论】:
以上是关于JavaFX 使用动画最小化和最大化未装饰的舞台的主要内容,如果未能解决你的问题,请参考以下文章