简体   繁体   中英

Stop screen tearing with JavaFX AnimationTimer

In JavaFX, it seems appropriate to me to use AnimationTimer for frequently updating Canvas Nodes; that is, for rasterized animations instead of vector animations. I'm running into an issue, which may be VSync related. I have a singular Canvas on my Scene which contains 2D data that changes frequently (the rest of the program is done with Nodes). I tend to get a tearing down the middle of the screen when I do this, which implies that the AnimationTimer may be falling out of sync with the monitor refresh rate.

This (simplified) code shows the error in detail. Note that I have no idea whether it's display hardware dependent, and the exact position of the tear may shift slightly.

import javafx.application.*;
import javafx.animation.*;
import javafx.scene.*;
import javafx.scene.canvas.*;
import javafx.stage.*;
import javafx.event.*;
import javafx.scene.input.*;
import javafx.scene.paint.*;

public class BugDemo extends Application {

    public static void main(String...args) {
        launch(args);
    }

    private Canvas background = new Canvas();
    private Color bgColor = Color.rgb(0, 0, 0);

    @Override
    public void start(Stage primaryStage) throws Exception {
        Group root = new Group();

        startLoops(root);
        Scene scene = new Scene(root);

        initUserControls(scene);
        background.widthProperty().bind(scene.widthProperty());
        background.heightProperty().bind(scene.heightProperty());
        root.getChildren().add(background);

        primaryStage.setScene(scene);

        primaryStage.setTitle("Bug Demo");

        primaryStage.setMaximized(true);
        primaryStage.show();
    }

    /**
     * Initializes all running control managers for game field
     * @param scene primary scene of game
     */
    protected void initUserControls(Scene scene) {
        EventHandler<MouseEvent> handler = new EventHandler<MouseEvent>(){

            @Override
            public void handle(MouseEvent event) {
                bgColor = Color.rgb((int)((event.getX() / background.getWidth()) * 255),
                        (int)((event.getY() / background.getHeight()) * 255),
                        255);
            }};
        scene.getRoot().setOnMouseMoved(handler);
        scene.getRoot().setOnMouseDragged(handler);
    }

    /**
     * Starts all game loops, which will at the beginning of the simulation and often for the extent
     * of it.
     * @param parent Root node
     */
    protected void startLoops(Parent parent) {
        GraphicsContext gc = background.getGraphicsContext2D();

        new AnimationTimer() {

            @Override
            public void handle(long now) {
                drawBackground(gc);
            }}.start();
    }

    protected void drawBackground(GraphicsContext gc) {
        gc.setFill(bgColor);
        gc.fillRect(0, 0, background.getWidth(), background.getHeight());
    }

}

Moving the mouse cursor over the scene will cause the canvas to shift in background color. As you move the mouse, you will notice (presumably) a tearing in the frame.

It is quite possible that I'm simply being a N00B at JavaFX, and there's a perfectly friendly .sync()-ish method I'm supposed to call somewhere; but I haven't found it yet. I've found bugs submitted to Oracle that look similar to this. My answer may simply be dodging using Canvas and AnimationTimer for animations. All the same, even if there isn't a solution at this time, if someone has a workaround, I would love to hear about it!

Thanks!

Found the issue (thank you to @VGR for pointing out the lack of system behavioral congruity)! Seems that it wasn't Java at all; it was Marco. I switched Desktop Windowing Managers, to Compiz specifically; and the tearing is now gone.

Evidently this isn't a bug in Java at all; it's a trade-off for using Marco. This is a relief!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM