2013-12-13 3 views
8

Ich möchte den Cursor in Cursor.WAIT ändern, wenn potenziell lange Operationen in JavaFX-Anwendung ausgeführt werden. Ich dachte, dass Platform.runLater wird mir helfen:Cursor in JavaFX-Anwendung für lange Operationen ändern

this.getStage().getScene().setCursor(Cursor.WAIT); 

Platform.runLater(new Runnable() { 
    @Override 
    public void run() { 
     // Do some stuff 
     getStage().getScene().setCursor(Cursor.DEFAULT); 
    } 
}); 

Aber Cursor ändert sich nicht. Warum funktioniert das nicht? Aus dem JavaFX Anwendungsthread

+1

setCursor sollte auf dem FX-Thread aufgerufen werden ... – assylias

Antwort

16

Angenommen, Sie den folgenden Code ausführen, könnte ein Muster mit einer Wartecursor für die Anzeige sein:

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

// Do some stuff 

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

Oder, wenn Sie bereits auf dem JavaFX Anwendungsthread sind, könnten Sie ein Service:

import javafx.application.Application; 
import javafx.beans.binding.Bindings; 
import javafx.concurrent.*; 
import javafx.event.*; 
import javafx.geometry.*; 
import javafx.scene.*; 
import javafx.scene.control.*; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 

public class ServiceWithCursorControl extends Application { 
    private final Button runButton = new Button("Run"); 
    private final Label label = new Label(); 

    private final Service service = new Service() { 
     @Override 
     protected Task createTask() { 
      return new Task<Void>() { 
       @Override protected Void call() throws Exception { 
        // do stuff 
        Thread.sleep(5000); 
        return null; 
       } 
      }; 
     } 
    }; 

    @Override public void start(Stage stage) { 
     VBox layout = createLayout(); 

     Scene scene = new Scene(layout, 100, 80); 
     stage.setScene(scene); 

     bindUIandService(stage); 

     stage.show(); 
    } 

    private void bindUIandService(Stage stage) { 
     label.textProperty() 
       .bind(
         service.stateProperty().asString() 
       ); 

     stage.getScene() 
       .getRoot() 
       .cursorProperty() 
       .bind(
         Bindings 
          .when(service.runningProperty()) 
           .then(Cursor.WAIT) 
           .otherwise(Cursor.DEFAULT) 
       ); 

     runButton 
       .disableProperty() 
       .bind(
         service.runningProperty() 
       ); 

     runButton.setOnAction(new EventHandler<ActionEvent>() { 
      @Override 
      public void handle(ActionEvent event) { 
       service.restart(); 
      } 
     }); 
    } 

    private VBox createLayout() { 
     VBox layout = new VBox(10); 

     layout.getChildren().setAll(runButton, label); 
     layout.setPadding(new Insets(10)); 
     layout.setAlignment(Pos.CENTER); 

     return layout; 
    } 

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

es ist unklar, aus Ihrer Beschreibung, welche Ansatz Ihr Problem am besten passt, aber hoffentlich können Sie es trainieren.

+0

Sorry, ich dachte, es war offensichtlich, dass ich auf dem Hauptthread war. Der Service ist definitiv der richtige Weg. Danke für die großartige Antwort, es hat eine ganz neue Art des Denkens für mich eröffnet. –

+0

@jewelsea Das sieht so aus, als könnte es gut für das funktionieren, was ich brauche, aber ich bekomme eine Ausnahme. Ich muss eine potenziell große Anzahl benutzerdefinierter Steuerelemente (bis zu 50) initialisieren und sie in einem Rasterbereich auffüllen. Vielleicht könntest du mir dabei helfen? bitte sehen Sie diese Pastebin: http://pastebin.com/Mh2XZA9x – Will

+0

@Will Sieht aus wie ein anderes Problem als diese Frage bezieht sich auf, bitte als eine neue Frage stellen. – jewelsea

Verwandte Themen