gpt4 book ai didi

javafx-2 - 在异步加载 ListView 项目期间显示 ProgressIndicator

转载 作者:行者123 更新时间:2023-12-01 09:00:03 25 4
gpt4 key购买 nike

我试图在执行异步后台 ProgressIndicator 项目加载时显示 ListView。我想要的行为是:

  • 在开始加载 ListView 项之前,显示一个带有 indeterminate 进度的 ProgressIndicator
  • 异步开始加载 ListView 项;
  • ListView 项加载完成后,隐藏 ProgressIndicator

  • 这是我未成功尝试的 ssce:
    public class AsyncLoadingExample extends Application {
    public static void main(String[] args) {
    launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
    final ListView<String> listView = new ListView<String>();
    final ObservableList<String> listItems = FXCollections.observableArrayList();
    final ProgressIndicator loadingIndicator = new ProgressIndicator();
    final Button button = new Button("Click me to start loading");

    primaryStage.setTitle("Async Loading Example");

    listView.setPrefSize(200, 250);
    listView.setItems(listItems);

    loadingIndicator.setVisible(false);

    button.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
    // I have hoped it whould start displaying the loading indicator (actually, at the end of this
    // method execution (EventHandler.handle(ActionEvent))
    loadingIndicator.setVisible(true);

    // asynchronously loads the list view items
    Platform.runLater(new Runnable() {
    @Override
    public void run() {
    try {
    Thread.sleep(2000l); // just emulates some loading time

    // populates the list view with dummy items
    while (listItems.size() < 10) listItems.add("Item " + listItems.size());
    } catch (InterruptedException e) {
    e.printStackTrace();
    } finally {
    loadingIndicator.setVisible(false); // stop displaying the loading indicator
    }
    }
    });
    }
    });

    VBox root = VBoxBuilder.create()
    .children(
    StackPaneBuilder.create().children(listView, loadingIndicator).build(),
    button
    )
    .build();

    primaryStage.setScene(new Scene(root, 200, 250));
    primaryStage.show();
    }
    }

    在这个例子中, ListView 项是异步加载的。但是, ProgressIndicator 没有出现。仍然在这个例子中,如果我省略了所有的 Platform.runLater(...) 代码, ProgressIndicator 就会出现,但是,当然, ListView 项不会被加载。

    因此,我怎样才能实现所需的行为?

    最佳答案

    Crferreira 的自我回答非常好。

    此答案仅演示了不需要使用任何 Platform.runLater 调用而是使用 JavaFX Task (以及 Java 8 lambda syntax )的替代实现。

    import javafx.application.Application;
    import javafx.collections.*;
    import javafx.concurrent.Task;
    import javafx.scene.Scene;
    import javafx.scene.control.*;
    import javafx.scene.layout.*;
    import javafx.stage.Stage;
    import java.util.*;

    public class AsyncLoadingExample extends Application {
    private void loadItems(final ObservableList<String> listItems, final ProgressIndicator loadingIndicator) {
    if (loadingIndicator.isVisible()) {
    return;
    }

    // clears the list items and start displaying the loading indicator at the Application Thread
    listItems.clear();
    loadingIndicator.setVisible(true);

    // loads the items at another thread, asynchronously
    Task listLoader = new Task<List<String>>() {
    {
    setOnSucceeded(workerStateEvent -> {
    listItems.setAll(getValue());
    loadingIndicator.setVisible(false); // stop displaying the loading indicator
    });

    setOnFailed(workerStateEvent -> getException().printStackTrace());
    }

    @Override
    protected List<String> call() throws Exception {
    final List<String> loadedItems = new LinkedList<>();

    Thread.sleep(2000l); // just emulates some loading time

    // populates the list view with dummy items
    while (loadedItems.size() < 10) {
    loadedItems.add("Item " + loadedItems.size());
    }

    return loadedItems;
    }
    };

    Thread loadingThread = new Thread(listLoader, "list-loader");
    loadingThread.setDaemon(true);
    loadingThread.start();
    }

    @Override
    public void start(Stage primaryStage) {
    final ListView<String> listView = new ListView<>();
    final ObservableList<String> listItems = FXCollections.observableArrayList();
    final ProgressIndicator loadingIndicator = new ProgressIndicator();
    final Button button = new Button("Click me to start loading");

    primaryStage.setTitle("Async Loading Example");

    listView.setPrefSize(200, 250);
    listView.setItems(listItems);

    loadingIndicator.setVisible(false);

    button.setOnAction(event -> loadItems(listItems, loadingIndicator));

    VBox root = new VBox(
    new StackPane(
    listView,
    loadingIndicator
    ),
    button
    );

    primaryStage.setScene(new Scene(root, 200, 250));
    primaryStage.show();
    }

    public static void main(String[] args) { launch(args); }
    }

    关于javafx-2 - 在异步加载 ListView 项目期间显示 ProgressIndicator,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18923413/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com