Java – force UI update

I have a piece of code to capture screen shots of nodes in 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;
    }
}

It has a twist, that is, it should hide the given nodes before interception (if they overlap with nodes, it is clear in some cases.)

However, it's hard for me to find a way to force redrawing to include opacity changes before taking screenshots - the only reference I've found is requestlayout (), but it's no fun

What method should I call to force and wait for redrawing to complete?

Solution

I think your code is strange:

>Why use node Setopacity (0) makes it invisible instead of node setVisible(false)? > Why return AWT bufferedimage instead of JavaFX image? > Why use a robot to capture the screen instead of taking a snapshot of the scene? > Why mix swing and JavaFX and end up having to worry about rendering order?

Maybe there are reasons why I don't understand these things, but I just do this:

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;
}

I created a small sample app that uses the above routine

The main window includes groups with circles and rectangles When the snapshot command is issued, the rectangle is hidden in the main mode, the main snapshot is taken, and then the rectangle is displayed in the main mode again

To answer questions about forced UI updates, title - you really can't JavaFX application thread and JavaFX rendering thread will be regarded as two separate things What you need to do is run the process on the JavaFX application thread, return control to the JavaFX system, wait for it to render, and then check the results scene. The snapshot method handles synchronization for you, so you don't have to worry about it

For whatever reason, if scene If the snapshot is not suitable for you and you want to keep the content similar to the original policy, what you should do is:

>Issue some update commands on the JavaFX application thread (for example, set the node opacity to 0). > Issue platform Runlater calls and gets the robot snapshot in the runlater body. > Once the snapshot is actually taken (notified in some AWT callbacks), issue another platform Runlater command to return the JavaFX application thread. > Return to the JavaFX application thread and issue more update commands (for example, set the node opacity back to 1)

This should work because it will allow the JavaFX system to execute another pulse to perform a screen rendering layout with opacity changes before the robot actually takes a snapshot Another mechanism is to use JavaFX animationtimer, which will provide you with callback when JavaFX pulse occurs Keeping all this in sync between AWT and JavaFX threads would be annoying

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>