0

I'm trying to understand how JavaFX and threads work together and I've stumbled upon a problem that I can't understand. So I wrote a little bit of code to try to make the problem as small as possible.
The idea of the program: a black rectangle can be dragged (it gets red as soon as this happens). When the mouse is released, the rectangle is put back to (0,0), the program waits one second and the rectangle becomes black again.

I know that this kind of question has been posted a lot, but I somewhat cannot find the right way to handle this correctly. I tried different solutions with Platform.runLater(), but I can't seem to make it work. As you can see if you run this code, the delay happens before relocating to (0,0) when the mouse is released.
What is it that I'm doing wrong?

public class App extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        Scene scene = new Scene(createRectangle());

        primaryStage.setScene(scene);
        primaryStage.setHeight(400);
        primaryStage.setWidth(400);
        primaryStage.show();
    }

    public Pane createRectangle() {
        Pane p = new Pane();
        Rectangle r = new Rectangle(50, 50);

        r.setOnMouseDragged(e -> {
            r.setFill(Paint.valueOf("red"));
            r.relocate(e.getSceneX(), e.getSceneY());
        });

        r.setOnMouseReleased(e -> {
            r.relocate(0, 0);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            r.setFill(Paint.valueOf("black"));

        });

        p.getChildren().addAll(r);

        return p;
    }
}
ubi
  • 103
  • 1
  • 1
  • 4
  • 3
    Never sleep the FX Application thread. (It will prevent any rendering from happening during the pause.) You don't need threads at all for this, use a `PauseTransition`. See (among many others) https://stackoverflow.com/questions/35369591/updating-your-ui-and-forcibly-waiting-before-continuing-javafx – James_D May 17 '20 at 15:00
  • Thanks James, that did the trick, and seems to be what I looked for! But why does the delay with Thread.sleep happen before the relocate command? Is it somehow asynchronous or so? – ubi May 17 '20 at 17:28
  • 1
    It doesn't happen before the `relocate()` call, you just don't see the effect of the `relocate()` call until the scene is rendered again. You can think of the FX Application Thread as a loop that repeatedly checks 1. if there are user events to handle, 2. if there are animations to process, and 3. if it's time to render the scene. If you call `sleep()` on that thread, it stops it for a time, so it never gets to draw the scene. – James_D May 17 '20 at 17:40

0 Answers0