2012-02-06 13 views
9

TilePaneに最大9個のパネルをロードしたいと思います。各ペインに対して、私はコンテンツの計算(約300ms)と第2のパネル(約500ms)を構築する必要があります。私が望むのは、計算後にすべてのパネルと交換する9つのプログレス・インジケータがあるということです。 私はPlatform.runlaterコマンドとサービスクラスで試してみました。結果は常に同じでした。 ProgressIndicatorは表示されますが、アニメートされません。秒後にすべてのパネルが一度に表示されます。 インジケータが時間の隙間に活気づけられ、次々と交換できる可能性はありますか?JavaFXのバックグラウンドでタスクを実行

答えて

11

JavaFXにはUIイベントに使用するイベントディスパッチスレッドがあります。 UIのすべての作業はこのスレッドで行われます。 UIの遅れを避けるために、UI以外の計算を行ってはいけません。

は、次のコードを参照してください:

public class Indicators extends Application { 

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

    @Override 
    public void start(Stage stage) { 
     Pane root = new HBox(); 
     stage.setScene(new Scene(root, 300, 100)); 

     for (int i = 0; i < 10; i++) { 
      final ProgressIndicator pi = new ProgressIndicator(0); 
      root.getChildren().add(pi); 

      // separate non-FX thread 
      new Thread() { 

       // runnable for that thread 
       public void run() { 
        for (int i = 0; i < 20; i++) { 
         try { 
          // imitating work 
          Thread.sleep(new Random().nextInt(1000)); 
         } catch (InterruptedException ex) { 
          ex.printStackTrace(); 
         } 
         final double progress = i*0.05; 
         // update ProgressIndicator on FX thread 
         Platform.runLater(new Runnable() { 

          public void run() { 
           pi.setProgress(progress); 
          } 
         }); 
        } 
       } 
      }.start(); 
     } 

     stage.show(); 

    } 
} 
+0

こんにちはセルゲイ...私は疑問を持って、私は、アプリケーション内で実行されているこれらのスレッドのいくつかを持つことができます?ありがとう。 –

+1

@MarcoR、確かに、 'new Thread()'を何回か実行することができます。 –

+0

Sergeyに感謝します.ApplicationにいくつかのPlatform.runLaterを持つことをお勧めしますか?これらのスレッドはビューを変更する必要があるため、ダイアログを表示するかどうかを検証します。 –

12

これは私がこの問題を解決する方法である:

import java.util.Random; 

import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.concurrent.Service; 
import javafx.concurrent.Task; 
import javafx.concurrent.Worker; 
import javafx.concurrent.Worker.State; 
import javafx.geometry.Insets; 
import javafx.scene.Group; 
import javafx.scene.Node; 
import javafx.scene.Scene; 
import javafx.scene.control.Label; 
import javafx.scene.control.ProgressBar; 
import javafx.scene.control.ProgressIndicator; 
import javafx.scene.layout.StackPane; 
import javafx.scene.layout.TilePane; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Rectangle; 
import javafx.stage.Stage; 


public class Minimal extends Application { 

private TilePane loadPane; 
private ProgressIndicator[] indicators = new ProgressIndicator[9]; 
private Label loading[] = new Label[9]; 
private Color[] colors = {Color.BLACK,Color.BLUE,Color.CRIMSON,Color.DARKCYAN,Color.FORESTGREEN,Color.GOLD,Color.HOTPINK,Color.INDIGO,Color.KHAKI}; 
private int counter = 0; 

@Override 
public void start(Stage primaryStage) throws Exception { 
    //creating Layout 
    final Group root = new Group();        
    Scene scene = new Scene(root, 400, 400);    
    primaryStage.setScene(scene); 
    primaryStage.setResizable(false); 
    StackPane waitingPane = new StackPane(); 
    final ProgressBar progress = new ProgressBar(); 
    Label load = new Label("loading things..."); 
    progress.setTranslateY(-25); 
    load.setTranslateY(25); 
    waitingPane.getChildren().addAll(new Rectangle(400,400,Color.WHITE),load,progress); 
    root.getChildren().add(waitingPane); 

    //Task for computing the Panels: 
    Task<Void> task = new Task<Void>() { 
     @Override 
     protected Void call() throws Exception { 
      for (int i = 0; i < 20; i++) { 
       try { 
        Thread.sleep(new Random().nextInt(1000)); 
       } catch (InterruptedException ex) { 
        ex.printStackTrace(); 
       } 
       final double prog = i*0.05; 
       Platform.runLater(new Runnable() { 
        public void run() { 
         progress.setProgress(prog); 
        } 
       }); 
      } 
      return null; 
     } 
    }; 

    //stateProperty for Task: 
    task.stateProperty().addListener(new ChangeListener<Worker.State>() { 

     @Override 
     public void changed(ObservableValue<? extends State> observable, 
       State oldValue, Worker.State newState) { 
      if(newState==Worker.State.SUCCEEDED){ 
       loadPanels(root); 
      } 
     } 
    }); 

    //start Task 
    new Thread(task).start(); 

    primaryStage.show(); 
} 

private void loadPanels(Group root) { 
    //change to loadPanel: 
    root.getChildren().set(0,createLoadPane()); 

    //Service: 
    final Service<Rectangle> RecBuilder = new Service<Rectangle>() { 
      @Override protected Task<Rectangle> createTask() { 
       return new Task<Rectangle>() { 
        @Override protected Rectangle call() throws InterruptedException { 
         updateMessage("loading rectangle . . ."); 
         updateProgress(0, 10); 
         for (int i = 0; i < 10; i++) { 
         Thread.sleep(100); 
         } 
         updateMessage("Finish!"); 
         return new Rectangle((380)/3,(380)/3,colors[counter]); 
        } 
       }; 
      } 
    }; 

    //StateListener 
    RecBuilder.stateProperty().addListener(new ChangeListener<Worker.State>() { 
     @Override public void changed(ObservableValue<? extends Worker.State> observableValue, 
         Worker.State oldState, Worker.State newState) { 
      switch (newState) { 
      case SCHEDULED: 
       break; 
      case READY: 
      case RUNNING: 
       break; 
      case SUCCEEDED: 
       Rectangle rec = RecBuilder.valueProperty().getValue(); 
       indicators[counter].progressProperty().unbind(); 
       loading[counter].textProperty().unbind(); 
       loadPane.getChildren().set(counter, rec); 
       if(counter<8){ 
        counter++; 
        nextPane(RecBuilder); 
       } 
       break; 
      case CANCELLED: 
      case FAILED: 
       loading[counter].textProperty().unbind(); 
       loading[counter].setText("Failed!"); 
       if(counter<8){ 
        counter++; 
        nextPane(RecBuilder); 
       } 
       break; 
      } 
     } 
    }); 

    //begin PanelBuilding: 
    nextPane(RecBuilder); 
} 

private void nextPane(Service<Rectangle> recBuilder) { 
    loading[counter].textProperty().bind(recBuilder.messageProperty()); 
    indicators[counter].visibleProperty().bind(recBuilder.progressProperty().isNotEqualTo(new SimpleDoubleProperty(ProgressBar.INDETERMINATE_PROGRESS))); 
    recBuilder.restart(); 
} 

private Node createLoadPane() { 
    loadPane = new TilePane(5,5); 
    loadPane.setPrefColumns(3); 
    loadPane.setPadding(new Insets(5)); 
    for(int i=0;i<9;i++){ 
     StackPane waitingPane = new StackPane(); 
     Rectangle background = new Rectangle((380)/3, (380)/3, Color.WHITE); 
     indicators[i] = new ProgressIndicator(); 
     indicators[i].setPrefSize(50, 50); 
     indicators[i].setMaxSize(50, 50); 
     indicators[i].setTranslateY(-25); 
     indicators[i].setTranslateX(-10); 
     loading[i] = new Label(); 
     loading[i].setTranslateY(25); 
     waitingPane.getChildren().addAll(background,indicators[i],loading[i]); 
     loadPane.getChildren().add(waitingPane); 
    } 

    return loadPane; 
} 

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

} 
+0

ありがとうございます。私は問題は、タスク(より良い単一のタスクインスタンス)が複数回実行できないことだと思います。すべてのメソッド呼び出しでタスクインスタンスを再初期化するメソッドにタスクインスタンスを配置すると、それも私のために解決されました。ニース:) –

関連する問題