1

我有一个实现可初始化的控制器类,它看起来像这样:

public class FileSharingController implements Initializable {

private ObservableList<User> UsersListData;
@FXML
private ListView<User> UsersList;

@Override
public void initialize(URL location, ResourceBundle resources) {
final Task<Void> UsersListTask=new Task<Void>(){
            protected Void call() throws SQLException{
                DatabaseManager DB=new DatabaseManager();
                UsersListData.clear();
                UsersListData.addAll(DB.returnUsers());
                UsersList.setItems(UsersListData);
                return null;}};
        new Thread(UsersListTask).start();

}

但是我的 ListView 没有更新!我应该怎么办?!

4

1 回答 1

3
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")
            );
        }
    }
}
于 2013-07-26T07:42:27.493 回答