JavaFX and the waitcursor is fixed in Java 8.u40!

Today there was a really normal java code like:

setCursor(Waitcursor);

execute something on the server

setCursor(Defaultcursor);

 

Now the problem… the waitcursor does not appear!

The Code in Swing is still working but not in JavaFX.

There is a (from my point of view) a problem in the current implementation!

Current posts on „stackoverflow“ and other needs a „Task“.

Here is my Implementation with a Testflag „testFlagToUseOnlySetCursor“ to disable my code.

[codesyntax lang=“java“]

import com.sun.javafx.tk.Toolkit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.Orientation;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

/**
 *
 * @author andre
 */
public class Cursortest extends Application {

    /**
     * Testflag to check the difference between the original Oracle
     * implementation for the cursor.
     *
     */
    private boolean testFlagToUseOnlySetCursor = false;
    private Scene scene;

    private void addWaitcursorHelper() {

        // The AnimationTimer runs one every Frame
        AnimationTimer timer = new AnimationTimer() {
            boolean wasRendered = false;

            @Override
            public void handle(long now) {
                if (Toolkit.getToolkit().isNestedLoopRunning()) {
                    // One rendering must be running once to display the cursor!
                    if (wasRendered) {
                        Toolkit.getToolkit().exitNestedEventLoop(scene, Boolean.FALSE);
                    }
                    // Flag for one Rendering successful
                    wasRendered = true;
                } else {
                    wasRendered = false;
                }

            }
        };
        timer.start();
    }
    /**
     * Blocking of all! Events when the operation is running
     */
    private EventHandler<Event> blockingHelper = new EventHandler<Event>() {

        @Override
        public void handle(Event event) {
            event.consume();
        }
    };

    @Override
    public void start(Stage primaryStage) {

        Button btn = new Button();
        btn.setText("Perform long action");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                performAction();
            }

        });

        FlowPane root = new FlowPane(Orientation.VERTICAL);
        root.getChildren().add(btn);

        scene = new Scene(root, 300, 250);
        // Helper activation
        if (!testFlagToUseOnlySetCursor) {
            addWaitcursorHelper();
        }
        primaryStage.setTitle("Waitcursordemo");
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    private void realCodeExecution() {
        for (int i = 0; i < 50; i++) {
            try {
                System.out.println("Perform: " + i);
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                Logger.getLogger(Cursortest.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private void activateWaitCursor() {
        if (scene.getCursor() == null || !scene.getCursor().equals(Cursor.WAIT)) {
            if (!testFlagToUseOnlySetCursor) {
                //Blocking the events because the user has the chance to click a button in 2 Frames
                scene.addEventFilter(EventType.ROOT, blockingHelper);
            }
            // No multiple activation of the waitcursor and the eventloop
            scene.setCursor(Cursor.WAIT);
            if (!testFlagToUseOnlySetCursor) {
                // Activate a extra eventloop to perform a little hack to draw 2 frames that the cursor is showing
                Toolkit.getToolkit().enterNestedEventLoop(scene);
            }
        }
    }

    private void deactiveWaitCursor() {
        // Remove the cursor on the next paint
        Platform.runLater(new Runnable() {

            @Override
            public void run() {
                if (scene != null) {
                    scene.setCursor(null);
                    scene.removeEventFilter(EventType.ROOT, blockingHelper);
                }
            }
        });

    }

    private void performAction() {
        activateWaitCursor();
        realCodeExecution();
        deactiveWaitCursor();
    }
}

[/codesyntax]