2017-08-26 49 views
-1

這是一個使用冒泡排序到IntegerList有幾分和推每次迭代的結果來從RxJava庫Subject,用一些延遲的簡單類。動畫JavaFX中使用RxJava而不阻斷GUI

public class Sorter { 
    private PublishSubject<List<Integer>> subject = PublishSubject.create(); 

    public void bubbleSort(int delay) throws InterruptedException { 
     List<Integer> ints = randomIntegers(0,200,10); 
     for (int i = 0; i < ints.size(); i++) { 
      for (int j = 0; j < ints.size() - 1; j++) { 
       if (ints.get(j) > ints.get(j + 1)) { 
        Collections.swap(ints, j, j + 1); 
        subject.onNext(ints); 
        Thread.sleep(delay); 
       } 
      } 
     } 
    } 

    private List<Integer> randomIntegers(int origin, int bound, int limit) { 
     return new Random() 
       .ints(origin, bound) 
       .limit(limit) 
       .boxed() 
       .collect(Collectors.toList()); 
    } 

    public PublishSubject<List<Integer>> getSubject() { 
     return subject; 
    } 
} 

我可以與樣品代碼很容易觀察到的結果:

int delay = 100; 
Sorter sorter = new Sorter(); 
PublishSubject<List<Integer>> subject = sorter.getSubject(); 
subject.subscribe(System.out::println); 
sorter.bubbleSort(delay); 

我想,但是,看到迭代的結果作爲移動代表的數字不同高度的矩形。我使用JavaFX。每次迭代之後,我想清除應用程序窗口並重繪所有內容。

public class Main extends Application { 

    private Group root; 

    @Override 
    public void start(Stage primaryStage) throws InterruptedException { 
     root = new Group(); 
     Scene scene = new Scene(root, 500, 500, Color.WHITE); 
     primaryStage.show(); 
     primaryStage.setScene(scene); 

     Sorter sorter = new Sorter(); 
     PublishSubject<List<Integer>> subject = sorter.getSubject(); 
     subject.subscribe(this::drawRectangles); 
     sorter.bubbleSort(100); 

    } 

    private void drawRectangles(List<Integer> integers) { 
     root.getChildren().clear(); 
     rectangles.clear(); 
     for (int i = 0; i<integers.size(); i++) { 
      Rectangle rectangle = new Rectangle(i * 20, 500 - integers.get(i), 10, integers.get(i)); 
      rectangle.setFill(Color.BLACK); 
      rectangles.add(rectangle); 
     } 
     root.getChildren().addAll(rectangles); 
    } 

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

但是,我只看到最後一次迭代的結果。在此之前,我只能看到應用程序正在運行並且GUI線程被阻塞。

如何使背景RxJava計算非阻塞到我的GUI?

編輯:我通過運行計算的代碼在另一個線程,像這樣解決問題:

@Override 
public void start(Stage primaryStage) throws InterruptedException { 

    new Thread(() -> { 
     Sorter sorter = new Sorter(); 
     sorter.getSubject().subscribe(this::drawRectangles); 
     try { 
      sorter.bubbleSort(100); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    }).start(); 


    root = new Group(); 
    Scene scene = new Scene(root, 1500, 500, Color.WHITE); 
    primaryStage.show(); 
    primaryStage.setScene(scene); 
} 

而且在Platform.runLater(() -> {}表達包裝器drawRectangles

這似乎是工作,雖然我覺得我可能有可能以某種方式運行此observeOn

回答

0

使用RxJavaFX調度程序您的UI任務。

您需要在另一個線程而不是UI線程中執行排序任務sorter.bubbleSort。和

observeOn(JavaFxScheduler.getInstance()) 

將UI任務調度回UI線程。

start方法只更改爲:

@Override 
    public void start(Stage primaryStage) throws InterruptedException { 
    root = new Group(); 
    Scene scene = new Scene(root, 500, 500, Color.WHITE); 
    primaryStage.show(); 
    primaryStage.setScene(scene); 

    Sorter sorter = new Sorter(); 
    sorter.getSubject() 
     .observeOn(JavaFxScheduler.platform()) 
     .subscribe(this::drawRectangles); 
    new Thread(() -> uncheck(() -> sorter.bubbleSort(100))).start(); 
    } 
+0

你使用哪個版本的RxJavaFX的?我無法編譯這段代碼,因爲'observeOn'期待'rx.Scheduler','JavaFxScheduler'是'io.reactivex.Scheduler'。另外,lambda表達式中的'uncheck'方法用於啓動一個帶有計算的新線程? – Scramjet

+0

@Scramjet對不起,我沒有說清楚。如果您使用RxJava1並將'JavaFxScheduler.platform()'更改爲'JavaFxScheduler.getInstance()',則可以使用RxJavaFX1。而'uncheck'是一個實用的方法,忽略檢查的異常。你可以使用'try ... catch ...'來忽略'InterruptException'。 –

+0

@Scramjet這裏是'RxJavaFX'的鏈接。 [LINK](http://www.mvnrepository.com/search?q=rxjavafx) –