- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个问题,就像在 JavaFX indeterminate progress bar while doing a process 中暴露的问题一样, 但我使用 javafx dialog Alert为了使用如下代码在进度条内显示对话框:
Alert busyWaitAlert = new Alert(
Alert.AlertType.INFORMATION);
busyWaitAlert.setContentText("Operation in progress");
ButtonType cancelButton = new ButtonType("Cancel", ButtonBar.ButtonData.FINISH);
busyWaitAlert.getButtonTypes().setAll(cancelButton);
busyWaitAlert.setTitle("Running Operation");
busyWaitAlert.setHeaderText("Please wait... ");
ProgressBar progressBar = new ProgressBar();
busyWaitAlert.setGraphic(progressBar);
progressBar.setProgress(ProgressBar.INDETERMINATE_PROGRESS);
Task<Boolean> task;
task = new Task<Boolean>() {
@Override
public Boolean call() throws Exception {
Collections.sort(LnkListImportedToDb, new importDataToDb.DataItemImportedToDbTimeCmp1());
return true;
}
};
task.setOnSucceeded((e) -> {
busyWaitAlert.close();
});
progressBar.progressProperty().bind(task.progressProperty());
busyWaitAlert.contentTextProperty().bind(task.messageProperty());
new Thread(task).start();
问题是在一个任务中,我调用了一个 Collection.Sort,我不知道它的持续时间,我不能在“任务调用”方法中执行 updateMessage,没有这个警告对话框卡住。我想通过在第一个任务的调用中插入另一个管理 Collection.sort 的任务来解决问题,是否有更好的解决方案?
最佳答案
Task
或更一般的 Worker
的目的是在后台线程上运行长时间运行的进程,同时能够向用户更新其进度。 Task
类为您提供了许多允许与 JavaFX 应用程序线程安全通信的方法,例如 updateProgress
、updateMessage
和 setOnSucceeded
。但是,您不需要使用这些功能来使用Task
;并且不使用这些功能不会以任何方式在功能上损害 Task
。
例如,您可以有一个非常简单的 Task
,如下所示:
public class TaskImpl<E> extends Task<Void> {
private final List<E> list;
public TaskImpl(List<E> list) { this.list = list; }
@Override protected Void call() throws Exception {
list.sort(null);
return null;
}
}
这里的代码并没有利用Task
,而是简单地用于在后台线程上对List
进行排序。外部代码仍然可以观察 Task
而不会产生不良影响。例如,您的 Alert
不会卡住,因为 message
和 progress
属性没有更新。
但是,如果您不打算使用 Task
的功能,您也可以只使用普通的旧式 Runnable
或 Callable
。以上在功能上等同于:
() -> list.sort(null);
Runnable
和 Task
(实现了 Runnable
)有一些共同点:两者都不会在单独的环境中运行自己线程给你。您实际上必须将工作传递给另一个线程。您可以通过直接创建 Thread
或更好的选择,使用 java.util.concurrent
包中提供的 Executor
框架来完成此操作.
尽管如此,我不确定我是否理解您遇到的问题。由于您不知道调用 List.sort
需要多长时间,Task
的 progress
属性应该只是保持不确定。如果你想显示一条消息,你可以这样做:
@Override protected Void call() {
updateMessage("Sorting...");
list.sort(null);
updateMessage("Sorting complete.");
updateProgress(1, 1); // jumps progress from indeterminate to 100%
return null;
}
然后将适当的控件绑定(bind)到适当的属性,将控件添加到 Alert
,并显示 Alert
。这是有关如何执行此操作的完整工作示例:
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ListView;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main extends Application {
private List<Integer> integerList;
@Override
public void init() {
/*
* If there is at least one parameter attempt to parse the
* first one as an Integer. This value will be used as the
* size of the randomly generated "integerList".
*
* If there are no parameters then default to 10 million.
*/
List<String> params = getParameters().getRaw();
if (!params.isEmpty()) {
generateRandomList(Integer.parseInt(params.get(0)));
} else {
generateRandomList(10_000_000);
}
}
private void generateRandomList(int size) {
System.out.printf("Generating random list of %,d integers...%n", size);
Random r = new Random();
integerList = Stream.generate(() -> r.nextInt(size))
.limit(size)
.collect(Collectors.toList());
System.out.println("List generated.");
}
@Override
public void start(Stage primaryStage) {
System.out.println("Building scene graph...");
ListView<Integer> listView = new ListView<>();
listView.setPrefWidth(500);
listView.getItems().addAll(integerList);
Button btn = new Button("Sort List");
btn.setOnAction(ae -> {
ae.consume();
btn.setDisable(true);
/*
* Here we create the task and configure it to set items of the listView
* to the result. We do this because we are sorting "integerList" which
* we had *copied* into the ListView. If we sorted the items of the ListView
* then we would be altering the UI from a background thread (big no-no!).
* Therefore we need to re-copy the "integerList" into the ListView upon
* completion of the task.
*/
SortingTask<Integer> task = new SortingTask<>(integerList, null);
task.setOnSucceeded(wse -> listView.getItems().setAll(task.getValue()));
Alert alert = createProgressAlert(primaryStage, task);
executeTask(task);
alert.show();
});
VBox root = new VBox(btn, listView);
root.setSpacing(10);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(20));
VBox.setVgrow(listView, Priority.ALWAYS);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setTitle("Progress Alert Example");
primaryStage.setResizable(false);
primaryStage.show();
System.out.println("Primary stage displayed.");
}
// executes task on a separate, daemon thread
private void executeTask(Task<?> task) {
Thread t = new Thread(task, "sorting-thread");
t.setDaemon(true);
t.start();
}
// creates the Alert and necessary controls to observe the task
private Alert createProgressAlert(Stage owner, Task<?> task) {
Alert alert = new Alert(Alert.AlertType.NONE);
alert.initOwner(owner);
alert.titleProperty().bind(task.titleProperty());
alert.contentTextProperty().bind(task.messageProperty());
ProgressIndicator pIndicator = new ProgressIndicator();
pIndicator.progressProperty().bind(task.progressProperty());
alert.setGraphic(pIndicator);
alert.getDialogPane().getButtonTypes().add(ButtonType.OK);
alert.getDialogPane().lookupButton(ButtonType.OK)
.disableProperty().bind(task.runningProperty());
alert.getDialogPane().cursorProperty().bind(
Bindings.when(task.runningProperty())
.then(Cursor.WAIT)
.otherwise(Cursor.DEFAULT)
);
return alert;
}
// The Task implementation
private static class SortingTask<E> extends Task<List<E>> {
private final List<E> list;
private final Comparator<? super E> comparator;
private SortingTask(List<E> list, Comparator<? super E> comparator) {
this.list = Objects.requireNonNull(list);
this.comparator = comparator; // if null then natural order is used by List.sort
updateTitle("Sorting Task");
}
@Override
protected List<E> call() throws Exception {
updateMessage("Sorting list...");
list.sort(comparator);
updateMessage("Sorting complete.");
updateProgress(1, 1);
return list;
}
@Override
protected void running() {
System.out.println("Sorting task is running...");
}
@Override
protected void succeeded() {
System.out.println("Sorting task successful.");
}
}
}
如果您希望自定义随机生成的列表的大小,您可以将一个整数作为参数传递给该程序。如果传递了多个参数,则忽略第一个参数。如果没有给出参数,则大小默认为 10,000,000(一千万)。根据您的计算机,您可能希望增加或减少列表的大小,以便 Task
不会完成得太快(或花费太长时间)。
关于Javafx如何实现忙等待对话例程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51387453/
我试图让脚本暂停大约 1 秒,然后继续执行脚本,但我似乎无法弄清楚如何做。这是我的代码: function hello() { alert("Hi!") //I need about a 1
wait() 和 wait(timeout) 之间有什么区别。无论如何 wait() 需要等待通知调用,但为什么我们有 wait(timeout)? 那么 sleep(timeout) 和 wait(
我需要做什么: 我有一个带有文件输入和隐藏文本输入的上传表单。用户上传图像,图像被操作,然后发送到远程服务器进行处理,这需要几秒钟,然后远程服务器将最终的图像发送回家庭服务器,并保存在新文件夹中。 J
大家好,我正在使用 Visual C++ 2010,尝试使用 Winsock 编写服务器/客户端应用程序...我不确定为什么,但有时服务器会在 listen() 函数处等待,有时会在 accept 处
任务描述 我为我的 Angular 应用程序实现了 CRSF 保护。服务器检查 crsf token 是否位于请求的 header “X-CSRF-TOKEN”中。如果不是,它会发送一个 HTTP 响
我想做这个例子https://stackoverflow.com/a/33585993/1973680同步。 这是正确的实现方式吗? let times= async (n,f)=>{
我如何将 while 循环延迟到 1 秒间隔,而不会将其运行的整个代码/计算机的速度减慢到一秒延迟(只是一个小循环)。 最佳答案 Thread.sleep(1000); // do nothing f
我知道这是一个重复的问题。但是我无法通过解释来理解。我想用一个很好的例子来清楚地理解它。任何人都可以帮忙吗。 “为什么我们从同步上下文中调用 wait()、notify() 方法”。 最佳答案 当我们
我有一个 click 事件,该事件是第一次从另一个地方自动触发的。我的问题是它运行得太快,因为所需的变量仍在由 Flash 和 Web 服务定义。所以现在我有: (function ($) {
我有如下功能 function async populateInventories(custID){ this.inventories = await this.inventoryServic
我一直对“然后”不被等待的行为感到困扰,我明白其原因。然而,我仍然需要绕过它。这是我的用例。 doWork(family) { return doWork1(family)
我想我理解异步背后的想法,返回一个Future,但是我不清楚异步在一个非常基本的层面上如何表现。据我了解,它不会自动在程序中创建异步行为。例如: import 'dart:async'; main()
我正在制作一个使用异步的Flutter应用程序,但它的工作方式不像我对它的了解。所以我对异步和在 Dart 中等待有一些疑问。这是一个例子: Future someFunction() async {
我在 main.tf 中创建资源组和 vNet,并在同一文件中引用模块。问题是,模块无法从模块访问这些资源。相关代码(删除了大部分代码,只留下相关部分): main.tf: module "worke
我的代码的问题是,当代码第一次运行时,我试图获取的 dom 元素并不总是存在,如果它不存在,那么永远不会做出 promise 。 我是否可以等到 promise 做出后再尝试实现它? 我希望我的最后一
所以,过去几天我一直在研究这段代码,并尝试实现回调/等待/任何需要的东西,但没有成功。 问题是,我如何等待响应,直到我得到两个函数的回调? (以及我将如何实现) 简而言之,我想做的是: POST 发生
谁能帮我理解这一点吗? 如果我们有一个类: public class Sample{ public synchronized method1(){ //Line1 .... wait();
这是我编写的代码,用于测试 wait() 和 notify() 的工作。现在我有很多疑问。 class A extends Thread { public void run() { try
我有以下代码由于语法错误而无法运行(在异步函数外等待) 如何使用 await 定义变量并将其导出? 当我这样定义一个变量并从其他文件导入它时,该变量是只创建一次(第一次读取文件时?)还是每次导入时都创
一个简单的线程程序,其中写入器将内容放入堆栈,读取器从堆栈中弹出。 java.util.Stack; import java.util.concurrent.ExecutorService; impo
我是一名优秀的程序员,十分优秀!