JavaFX does not repaint when removing an object drawn on top of another object


Question

In the code below, the green rectangle is not removed on mouse click. However, if you resize the stage after the mouse click, the scene is repainted and the green rect vanishes.

If you set the green rectangle's size to 150/150, then some of it is immediately on top of the pane, and it vanishes immediately on mouse click.

  • Is this a JavaFX bug, or am I overlooking something?
  • How can I make the rectangle disappear on mouse click?

My environment: Windows 7 / Java 1.8.0 64-Bit Server VM build 25.0-b70.

package xschach.client;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class Main3 extends Application {
    public static void main(String[] args) {
        Application.launch(Main3.class.getName());
    }

    public Main3() {}

    @Override
    public void start(Stage stage) throws Exception {
        Pane pane = new Pane();
        Rectangle rect = new Rectangle(10, 10, 200, 200);
        pane.getChildren().add(rect);
        stage.setScene(new Scene(pane, 300, 300));
        stage.show();

        Rectangle rect2 = new Rectangle(100, 100, 50, 50);
        rect2.setFill(Color.GREEN);
        pane.getChildren().add(rect2);

        pane.setOnMouseClicked(event -> pane.getChildren().remove(rect2));
    }
}
1
3
11/10/2014 7:06:08 AM

Accepted Answer

It really seems to me a bug.

Doing some tests, what happens is the very last node (on top), no matter how many we have, that lays within the bounds of the first one, when it's removed, it is not visible to the scene graph, it's not marked as dirty, and no requestLayout() is called.

I've found also other workaround. Just allow some (minimal) transparency to the first child, and it will work...

rect.setFill(Color.web("000000FE"));

And you can always put this node behind the first one...

pane.setOnMouseClicked(event -> {
     rect2.toBack();
     pane.getChildren().remove(rect2);
});

Anyway, consider filing a bug to Jira.

3
11/10/2014 12:38:48 PM

I know it's a little bit late, but it might help someone.

If you use the method .clear() on the children list of the pane if forces the render of the view. So this solution, quite extreme, I admit it, works :

pane.setOnMouseClicked(event -> {
       pane.getChildren().clear();
       pane.getChildren().add(rect);
    });

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon