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]
