GOXR3PLUS
GOXR3PLUS

Reputation: 7255

JavaFX capture screen using Robot

I am using a transparent Stage in JavaFX which contains a Canvas.

The user can draw a rectangle in the canvas by dragging the mouse.

When he hits enter i am saving the image using:

try {
     ImageIO.write(bufferedImage,extension,outputFile);
} catch (IOException e) {
    e.printStackTrace();                        
}

To capture the image from screen i am using:

gc.clearRect(0, 0, getWidth(), getHeight()); // [gc] is the graphicsContext2D of the Canvas

        // Start the Thread
        new Thread(() -> {
            try {

                // Sleep some time
                Thread.sleep(100);

                // Capture the Image
                BufferedImage image;
                int[] rect = calculateRect();
                try {
                    image = new Robot().createScreenCapture(new Rectangle(rect[0], rect[1], rect[2], rect[3]));
                } catch (AWTException e) {
                    e.printStackTrace();
                    return;
                }

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }).start();

The problem:

I don't know when the JavaFX Thread will clear the Canvas so i am using a Thread as you can see above which is waiting 100 milliseconds and then capture the screen.But it is not working all the times,what i mean is that sometimes the Canvas has not been cleared and i get this image(cause Canvas has not been cleared yet):

enter image description here

instead of this:

enter image description here

The question:

How i know when the JavaFX has cleared the Canvas so i can capture the screen after that?

Mixing Swing with JavaFX is not recommended although that's the only way i know to capture screen with Java...

Upvotes: 0

Views: 1251

Answers (1)

James_D
James_D

Reputation: 209339

I really hope there's a better way to achieve what you want than this, but the canvas will be cleared the next time a "pulse" is rendered. So one approach would be to start an AnimationTimer and wait until the second frame is rendered:

gc.clearRect(0, 0, getWidth(), getHeight());
AnimationTimer waitForFrameRender = new AnimationTimer() {
    private int frameCount = 0 ;
    @Override
    public void handle(long timestamp) {
        frameCount++ ;
        if (frameCount >= 2) {
            stop();
            // now do screen capture...
        }
    }
};
waitForFrameRender.start();

Obviously, if you are doing the screen capture in a background thread, you need to also make sure you don't draw back onto the canvas before the capture occurs...

Upvotes: 1

Related Questions