Baterka
Baterka

Reputation: 722

Canvas not redrawing after deletion in Group (JavaFX)

I have background (Rectangle) and Group added into root of canvas. I add smaller Rectangle (player) into group and then move rectangle by AnimationTimer (custom without thread sleep). When small Rectangle arrive centrain X position I want to remove this Rectangle from scene. After deletion, rectangle remains in canvas until I move/resize window. How to refresh canvas to make deleted rectangle disappear?

public class Test extends Application {

    public static final int TILE_SIZE = 50;
    public static final int WIDTH = 15;
    public static final int HEIGHT = 15;

    public static final int FRAMERATE = 30;

    private Pane root;

    private Group group = new Group();

    private Rectangle player;

    private Parent createContent() {
        root = new Pane();
        root.setPrefSize(500, 500);
        Rectangle bg = new Rectangle(500, 500);
        bg.setFill(Color.RED);

        root.getChildren().addAll(bg, group);

        AnimationTimer timer = new AnimationTimer() {
            @Override
            public void handle(long now) {
                onUpdate();
            }
        };
        timer.start();

        player = new Rectangle(20, 20);
        player.setFill(Color.GREEN);
        group.getChildren().add(player);

        return root;
    }

    public void onUpdate() {

        if (player.getTranslateY() > 100) {
            group.getChildren().remove(player);
        } else {
            player.setTranslateX(player.getTranslateX() + 1);
            player.setTranslateY(player.getTranslateY() + 1);
        }
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Scene scene = new Scene(createContent());
        primaryStage.setTitle("Test");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

Upvotes: 3

Views: 404

Answers (1)

James_D
James_D

Reputation: 209320

This is a known bug, which is still unresolved.

The workarounds suggested in the bug report are to disable dirty region optimizations, which you can do by providing the JVM option -Dprism.dirtyopts=false, i.e. run it as

java -Dprism.dirtyopts=false Test

You can also set this programmatically if your main method is in a class separate to the Application subclass (because you need to set it before the Application class is loaded):

import javafx.application.Application;

public class App {

    public static void main(String[] args) {
        System.setProperty("prism.dirtyopts", "false");
        Application.launch(Test.class, args);
    }
}

(and then just run the App class in the usual way).

Another workaround seems to be to ensure there is a more complex change to the group's list of child nodes, but this is not likely to be very robust. For example, the following seems to work in this particular case.

public void onUpdate() {


    if (player.getTranslateY() > 100) {
        Rectangle dummy = new Rectangle();
        group.getChildren().add(dummy);
        group.getChildren().remove(player);
        group.getChildren().remove(dummy);
    } else {
        player.setTranslateX(player.getTranslateX() + 1);
        player.setTranslateY(player.getTranslateY() + 1);
    }
}

Upvotes: 4

Related Questions