【发布时间】:2019-04-17 12:43:43
【问题描述】:
我一直在将我的一个项目迁移到 JavaFX 并开始遇到线程问题。我将附上一个简短的例子。经过大量搜索,我设法解决了问题。我无法在 fx 应用程序线程之外更改 tableView 数据。我将我的代码从使用 SwingWorker 切换到了 Task。
起初,这一直有效,直到我向表的 observableList 添加了一个更改侦听器。然后我收到错误“不在 FX 应用程序线程上;”
当我尝试更新标签的值时,onChanged 方法内部发生了错误。我通过将它包装在 Platform.runLater() 中解决了这个问题。
我只是对为什么更改标签表示它不在应用程序线程上感到困惑。这是在哪个线程上运行的?另外,我是否通过使用任务正确地将行添加到我的表中?在我的实际应用程序中,我可能会添加 50k 行,因此为什么要使用单独的线程以免锁定 UI。
public class Temp extends Application{
private ObservableList<String> libraryList = FXCollections.observableArrayList();
public void start(Stage stage) {
Label statusLabel = new Label("stuff goes here");
TableView<String> table = new TableView<String>(libraryList);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
TableColumn<String, String> col = new TableColumn<String, String>("Stuff");
col.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue()));
table.getColumns().add(col);
libraryList.addListener(new ListChangeListener<String>() {
public void onChanged(Change change) {
// Problem was caused by setting the label's text (prior to adding the runLater)
Platform.runLater(()->{
statusLabel.setText(libraryList.size()+" entries");
});
}
});
// dummy stuff
libraryList.add("foo");
libraryList.add("bar");
Button b = new Button("Press Me");
b.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
FileTask task = new FileTask();
new Thread(task).start();
}
});
BorderPane mainBody = new BorderPane();
mainBody.setTop(statusLabel);
mainBody.setCenter(table);
mainBody.setBottom(b);
Scene scene = new Scene(mainBody);
stage.setScene(scene);
stage.show();
}
class FileTask extends Task<Boolean>{
public FileTask(){
}
protected Boolean call() throws Exception{
Random rand = new Random();
for(int i = 0; i < 5; i++) {
String s = ""+rand.nextInt(Integer.MAX_VALUE);
libraryList.add(s);
}
return true;
}
}
public static void main(String[] args) {
Application.launch(args);
}
}
【问题讨论】:
-
两个注意事项:(1)您可以使用
Thread.currentThread()确定当前线程,(2)监听器由进行更改的线程调用。
标签: java multithreading javafx