2

I'm trying to change the cursor to indicate that the program is busy. It seems like this should be pretty simple, but I haven't been able to get it to work correctly and after searching for several hours, I haven't come up with the solution. Here's what I'm trying to do.

public class ButtonTest extends Application {
  @Override
  public void start(Stage primaryStage) {
    final StackPane root = new StackPane();
    primaryStage.setScene(new Scene(root, 200, 150));

    Button button = new Button();
    button.setText("Button");
    root.getChildren().add(button);

    primaryStage.show();

    button.setOnAction(new EventHandler<ActionEvent>() {
      @Override
      public void handle(ActionEvent event) {
        // Set the cursor to the wait cursor.
        root.setCursor(Cursor.WAIT);
        // Do some work.
        try {
          Thread.sleep(5000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        // Set the cursor back to the default.
        root.setCursor(Cursor.DEFAULT);
      }

    });
}

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

If I comment out the setCursor(Cursor.DEFAULT), after I press the button it waits 5 seconds then changes the cursor to the wait cursor. So it seems like it waiting until after the sleep, then executing setCursor(Cursor.WAIT), immediately followed by the setCursor(Cursor.DEFAULT). What am I missing?

Tim Fletcher
  • 125
  • 3
  • 13
  • See related: [JAVAFX:How to disable button for specific time?](http://stackoverflow.com/q/16919727) – Uluk Biy Jun 24 '13 at 16:58

2 Answers2

3

You're sleeping the main UI thread which is the same thread that's supposed to change the cursor shape. You need to kick off your sleep (or whatever expensive operation) on a background thread, while the main UI thread exits the handle method and returns to the UI event loop so that the cursor change can become active.

  • Thanks for the response. I've tried the following, but it doesn't work either. I have very little experience with threads, am I doing something wrong? – Tim Fletcher Jun 26 '13 at 17:10
  • Oops, hit enter too soon. I create a thread, start the thread, set the wait cursor, join the thread and the reset the cursor. But it still doesn't work. – Tim Fletcher Jun 26 '13 at 17:38
  • Don't join the thread! Just let the handler return. You must reset the cursor from inside the background thread method, via cross-thread invocation to the UI thread. –  Jun 26 '13 at 17:58
1

Have you ever tried Platform.runLater for this:

It should work like this:

primaryStage.getScene().setCursor(Cursor.WAIT);
Platform.runLater(new Runnable() {
  @Override
  public void run() {
    doSomethingInteresting();
    primaryStage.getScene().setCursor(Cursor.DEFAULT);
  }
});

The idea here is simple: in the original event just the mouse shape is defined and a new event is scheduled which will perform the action directly after this.

Ingo
  • 605
  • 6
  • 10