2017-08-11 17 views
0

我想更新管理多個建築物的應用程序。這些每個人都穿着它所包含的人數。每10秒鐘,每棟建築的人口增長1.如何從後臺週期性任務中修改模型屬性?

「更新」的意思是「從Swing到JavaFX的端口」。

目前的Swing應用程序實現與背景javax.swing.Timer線程週期性動作:

new Timer(10000, (e) -> { 
    for (Building building : theSuperKawaiBuildingList) { 
     building.setPopulation(building.getPopulation() + 1); 
    } 
}); 

...和model.Building是一個子類的java.util.Observable

public class Building extends Observable { 
    private int population; 

    public synchronized int getPoulation() { 
     return population; 
    } 

    public synchronized void setPoulation(int value) { 
     population = value; 

     setChanged(); 
     notifyObservers(); 
    } 

    public Building(int initPopulation) { 
     population = initPopulation; 
    } 
} 

現在,我喜歡使用JavaFX而不是Swing以及API的綁定功能來構建新的GUI,可能會執行model.Building類,如下所示:

public class Building { 
    // <editor-fold desc="FX Property - Population"> 
    private final IntegerProperty population; 
    public IntegerProperty populationProperty() { return population; } 
    public int getPopulation() { return population.get(); } 
    public void setPopulation(int value) { population.set(value); } 
    // </editor-fold> 

    public Building(int initPopulation) { 
     population = new SimpleIntegerProperty(initPopulation); 
    } 
} 

我想java.util.Timer可以適應法案,當涉及到定期的東西,但一些閱讀後,我懷疑更新一個屬性的(線程)安全性將被綁定到一個活動的場景圖一個後臺任務...

除非綁定帶有一些使我想做的事情變得可能的魔法,那麼最佳做法是什麼。

+0

上下文PS:我是一個JavaFX初學者,這將是我第一個使用這個框架的應用程序。 – Odepax

回答

1

如果場景圖中的UI組件的屬性綁定了背景線程,則無法更新模型中的屬性。

你可以用該更新Platform.runLater(...)的模式,所以它執行的FX應用程序線程調用:

new Timer(10000, (e) -> { 
    Platform.runLater(() -> { 
     for (Building building : theSuperKawaiBuildingList) { 
      building.setPopulation(building.getPopulation() + 1); 
     } 
    }); 
}); 

(或做一個java.util.Timer等效)。

另一種方法(可能更好)是使用JavaFX的動畫API:

Timeline timeline = new Timeline(); 
KeyFrame keyFrame = new KeyFrame(Duration.seconds(10), e -> { 
    for (Building building : theSuperKawaiBuildingList) { 
     building.setPopulation(building.getPopulation() + 1); 
    } 
}); 
timeline.getKeyFrames().add(keyFrame); 
timeline.setCycleCount(Animation.INDEFINITE); 
timeline.play(); 

上都在FX應用程序線程執行的時間線的部分關鍵幀的任何處理。

+0

好的,所以用動畫API實現後臺任務並不被認爲是「邪惡」?另外,我想我不會再需要那些「同步」了...... – Odepax

+0

順便說一下,如果該屬性沒有綁定到GUI,我可以更新屬性而不用擔心所有這些問題?就像,這個約束只來自GUI單線程設計。 – Odepax

+1

不,這可能是首選方法,*只要*您定期做的事情本身並不耗費時間(您發佈的示例就是這種情況)。如果您定期做一些耗時的工作,並且想在每個耗時任務結束時更新UI,請使用['ScheduledService'](http://docs.oracle.com/javase/) 8/JavaFX的/ API/JavaFX的/並行/ ScheduledService.html)。 –