final Task<List<User>> UsersListTask = new Task<List<User>>() {
protected List<User> call() throws SQLException {
return new DatabaseManager().returnUsers();
}
};
UsersListTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override public void handle(WorkerStateEvent event) {
UsersList.setItems(
FXCollections.observableArrayList(UsersListTask.getValue())
);
}
});
UsersListTask.setOnFailed(new EventHandler<WorkerStateEvent>() {
@Override public void handle(WorkerStateEvent event) {
System.out.println("ERROR: " + UsersListTask.getException());
}
});
new Thread(UsersListTask).start();
如果使用 java 8:
UsersListTask.setOnSucceeded(event ->
UsersList.setItems(
FXCollections.observableArrayList(UsersListTask.getValue())
)
);
UsersListTask.setOnFailed(event ->
System.out.println("ERROR: " + UsersListTask.getException())
);
请注意,您永远不应该从 JavaFX 线程更新支持 ListView 的项目列表,因为它可能会触发可能产生意外后果的场景图更新。通过对setOnSucceeded
方法中的项目列表执行更新,JavaFX 框架任务实现将在内部确保您的更新发生在 JavaFX 应用程序线程上。
示例代码
这是一个可执行示例,您可以尝试并与您的实现进行比较。
样本输出
列表.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<StackPane fx:controller="ListController" id="StackPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml">
<children>
<ListView fx:id="usersList"/>
</children>
</StackPane>
ListApplication.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.*;
import javafx.stage.Stage;
public class ListApplication extends Application {
@Override public void start(Stage stage) throws Exception{
Parent layout = FXMLLoader.load(getClass().getResource("list.fxml"));
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) { launch(args); }
}
ListController.java
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.concurrent.*;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
public class ListController {
@FXML private ListView<User> usersList;
@FXML void initialize() {
assert usersList != null : "fx:id=\"usersList\" was not injected: check your FXML file 'list.fxml'.";
final Task<List<User>> usersListTask = new Task<List<User>>() {
protected List<User> call() throws SQLException {
return new DatabaseManager().returnUsers();
}
};
usersListTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent event) {
usersList.setItems(
FXCollections.observableArrayList(usersListTask.getValue())
);
}
});
usersListTask.setOnFailed(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent event) {
System.out.println("ERROR: " + usersListTask.getException());
}
});
new Thread(usersListTask).start();
}
public static class User {
private final StringProperty name = new SimpleStringProperty();
public User(String name) {
this.name.set(name);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
@Override
public String toString() {
return getName();
}
}
public static class DatabaseManager {
public List<User> returnUsers() throws SQLException {
return Arrays.asList(
new User("Sally"),
new User("Jenny"),
new User("Jill"),
new User("Anne"),
new User("Carol"),
new User("Helen")
);
}
}
}