加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 强制UI更新

发布时间:2020-12-15 08:49:29 所属栏目:Java 来源:网络整理
导读:我有一段代码用于截取 JavaFX中的节点的屏幕截图: public BufferedImage getSnapshot(final Node... hideNodes) { Window window = getScene().getWindow(); Bounds b = localToScene(getBoundsInLocal()); int x = (int) Math.round(window.getX() + getSc
我有一段代码用于截取 JavaFX中的节点的屏幕截图:

public BufferedImage getSnapshot(final Node... hideNodes) {
    Window window = getScene().getWindow();
    Bounds b = localToScene(getBoundsInLocal());
    int x = (int) Math.round(window.getX() + getScene().getX() + b.getMinX());
    int y = (int) Math.round(window.getY() + getScene().getY() + b.getMinY());
    int w = (int) Math.round(b.getWidth());
    int h = (int) Math.round(b.getHeight());
    try {
        Robot robot = new Robot();
        for(Node node : hideNodes) {
            node.setOpacity(0);
            node.getParent().requestLayout();
        }
        BufferedImage image = robot.createScreenCapture(new java.awt.Rectangle(x,y,w,h));
        for(Node node : hideNodes) {
            node.setOpacity(1);
            node.getParent().requestLayout();
        }
        return image;
    }
    catch(AWTException ex) {
        return null;
    }
}

它有一个扭曲,那就是它应该在截取之前隐藏给定的节点(如果它们与节点重叠,在某些情况下是明确的.)

但是,我很难找到一种方法来强制重绘以在截取屏幕截图之前包含不透明度变化 – 我发现的唯一参考是requestLayout(),但没有任何乐趣.

我应该调用什么方法来强制并等待重绘完成?

解决方法

我觉得你的代码很奇怪:

>为什么使用node.setOpacity(0)使其不可见,而不是node.setVisible(false)?
>为什么返回AWT BufferedImage而不是JavaFX Image?
>为什么使用机器人来捕捉屏幕而不是拍摄场景的快照?
>为什么混合Swing和JavaFX并最终不得不担心渲染顺序?

也许这些事情有理由我不明白,但我只是这样做:

public Image takeSnapshot(Scene scene,final Node... hideNodes) {
  for (Node node: hideNodes) node.setVisible(false);
  Image image = scene.snapshot(null);
  for (Node node: hideNodes) node.setVisible(true);

  return image;
}

我创建了一个使用上述例程的小型sample app.

主窗口包括具有圆和矩形的组.发出快照命令时,矩形隐藏在主要模式中,拍摄主要快照,然后再次在主要模式中显示矩形.

?

要回答关于强制UI更新的问题标题 – 你真的不能. JavaFX应用程序线程和JavaFX呈现线程将被视为两个独立的事物.您需要做的是在JavaFX应用程序线程上运行处理,将控制权返回到JavaFX系统,等待它进行渲染,然后检查结果. scene.snapshot方法将为您处理同步,因此您不必担心它.

无论出于何种原因,如果scene.snapshot不适合您,并且您希望保留类似于原始策略的内容,那么您要做的是:

>在JavaFX应用程序线程上发出一些更新命令(例如,将节点不透明度设置为0).
>发出Platform.runLater调用并在runLater正文中获取机器人快照.
>一旦真正拍摄了快照(在某些awt回调中发出通知),请发出另一个Platform.runLater命令以返回JavaFX应用程序线程.
>返回JavaFX应用程序线程,发出更多更新命令(例如,将节点不透明度设置回1).

这应该工作,因为它将允许JavaFX系统执行另一个脉冲,在机器人实际拍摄快照之前执行不透明度更改的屏幕渲染布局.另一种机制是使用JavaFX AnimationTimer,它会在JavaFX脉冲发生时为您提供回调.在AWT和JavaFX线程之间保持所有这些的正确同步将是令人讨厌的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读