在集合已經綁定到JavaFX UI節點的線程中操作Observable集合的正確方法是什麼?更改線程中的Observable集合(綁定到JavaFX節點)
在我的示例應用程序中,線程可以進行任何操作之前,集合和節點之間的連接被中斷;然後在線程完成後重新連接。方法分別爲disconnectObservable()
和connectObservable()
。沒有這兩種方法,報告java.lang.IllegalStateException: Not on FX application thread
。
理想情況下,我希望ChangeObservableTask將其更改爲mWords
,然後我會調用某種方法告訴mObservable
自行刷新並通知其偵聽器。有這樣的事嗎?
謝謝。
package theapp;
import java.util.LinkedList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ThreadObList extends Application {
private final List<String> mWords;
private final ObservableList<String> mObservable;
private ListView mListView;
private Label mCount;
public ThreadObList() {
mWords = new LinkedList<>();
mObservable = FXCollections.observableList(mWords);
mWords.add("park");
}
@Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Start thread");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
ChangeObservableTask task = new ChangeObservableTask();
Thread thd = new Thread(task);
disconnectObservable();
thd.start();
try {
task.get();
System.out.println("ChangeObservableTask exited normally.");
}
catch(Exception ex) {
System.out.println(ex.getMessage());
}
connectObservable();
}
});
mCount = new Label();
mListView = new ListView();
VBox root = new VBox(5, btn, mCount, mListView);
VBox.setVgrow(mListView, Priority.ALWAYS);
connectObservable();
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private void connectObservable() {
mListView.setItems(mObservable);
mCount.textProperty().bind(Bindings.size(mObservable).asString());
}
private void disconnectObservable() {
mListView.setItems(null);
mCount.textProperty().unbind();
}
private class ChangeObservableTask extends Task<Void> {
@Override
protected Void call() throws Exception {
mObservable.add("dart");
mObservable.add("truck");
mObservable.add("ocean");
return null;
}
}
}
我會跟您的解決方案去。複製收藏可能會成爲一個問題,如果它非常大。我只能希望它永遠不會發生。 – deskwarrior 2014-09-01 14:52:55
還有其他選擇:例如如果你只是添加東西,只需在調用方法中創建並返回新列表,然後在'onSucceeded'中執行'addAll' ... – 2014-09-01 15:15:57