gpt4 book ai didi

JavaFX:ExecutorService.awaitTermination 不通过绑定(bind)属性更新 UI

转载 作者:行者123 更新时间:2023-11-30 07:18:17 26 4
gpt4 key购买 nike

我有多个任务在单个线程中运行。效果很好,相应的表格单元格进度条会按预期更新。现在,在执行它们之前,我想禁用 UI 上的所有按钮(这是我的 enableControls 方法)。当最后一个任务运行时,我重新启用按钮。

我尝试了以下操作,添加了关闭和 awaitTermination 但随后 UI 不会更新,除非所有操作都完成。

ExecutorService exec = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r);
t.setDaemon(true);
return t ;
});

enableControls(false);
for (Segment seg : selectedItems) {
Task loadingTask = new Task<Void>() {
@Override
public Void call() {
for (int i = 1; i <= 100; i++) {
updateProgress(i, 100);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
};
seg.progressBarProperty().bind(loadingTask.progressProperty());
loadingTask.setOnSucceeded(e -> seg.progressBarProperty().unbind());
loadingTask.setOnFailed(e -> {
loadingTask.getException().printStackTrace();
enableControls(true);
});
exec.submit(loadingTask);
}
exec.shutdown();
try {
exec.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test");
enableControls(true);

或者,我考虑确定当前任务是否是最后一个(循环中不再有段)并在 setOnSucceeded 中重新启用 UI 控件。至少可以说并不优雅。

知道为什么 UI(通过绑定(bind)值)没有更新 - 这是 awaitTermination 的限制吗?

最佳答案

awaitTermination是一个阻塞调用,您不应该在 JavaFX 应用程序线程上调用它。只需创建一个新任务来管理任务执行并等待其他任务终止。您可以使用新任务的绑定(bind)来在 UI 运行时禁用部分 UI。

run

import javafx.application.*;
import javafx.concurrent.Task;
import javafx.event.Event;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class Waiter extends Application {

private static final int N_TASKS = 3;
private static final int TOTAL_TASK_EXECUTION_TIME_LIMIT_SECS = 20;

private final VBox layout = new VBox(10);

@Override
public void start(Stage stage) throws Exception {
Button run = new Button("Run");
run.setOnAction(this::work);

layout.getChildren().add(run);
layout.setPadding(new Insets(10));
layout.setPrefSize(100, 150);

stage.setScene(new Scene(layout));
stage.show();
}

private void work(Event event) {
Node controlNode = (Node) event.getSource();

ExecutorService exec = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r, "load");
t.setDaemon(true);
return t;
});

ExecutorService monitor = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r, "monitor");
t.setDaemon(true);
return t;
});

final List<LoadingTask> tasks = new ArrayList<>();
for (int j = 0; j < N_TASKS; j++) {
LoadingTask loadingTask = new LoadingTask();
ProgressBar progressBar = new ProgressBar();
progressBar.progressProperty().bind(loadingTask.progressProperty());
layout.getChildren().add(progressBar);

tasks.add(loadingTask);
}

Task<Void> taskRunner = new Task<Void>() {
@Override
protected Void call() throws Exception {
tasks.forEach(exec::submit);
exec.shutdown();
boolean cleanShutdown = exec.awaitTermination(
TOTAL_TASK_EXECUTION_TIME_LIMIT_SECS,
TimeUnit.SECONDS
);
if (!cleanShutdown) {
exec.shutdownNow();
}

Platform.runLater(() ->
layout.getChildren()
.removeIf(
node -> node instanceof ProgressBar
)
);

return null;
}
};
controlNode.disableProperty().bind(taskRunner.runningProperty());
monitor.submit(taskRunner);
monitor.shutdown();
}

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

private static class LoadingTask extends Task<Void> {
@Override
public Void call() {
for (int i = 1; i <= 100; i++) {
if (isCancelled() || Thread.interrupted()) {
break;
}
updateProgress(i, 100);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
return null;
}
}
}

I need to disable all buttons and textfields on the stage

如果禁用父节点,它将递归地禁用父节点的所有子节点。因此禁用场景中的所有内容,只需绑定(bind)场景根的disableProperty即可:

controlNode.getScene().getRoot()
.disableProperty().bind(taskRunner.runningProperty());

禁用父阶段上的输入的另一种方法是使用 WINDOW_MODALAPPLICATION_MODAL与所有者集的对话。例如 ControlsFX ProgressDialog .

关于JavaFX:ExecutorService.awaitTermination 不通过绑定(bind)属性更新 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38024933/

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