我有一个并发任务,可以处于两种状态-活动(工作)和暂停(通过Thread.sleep(xxxx)). 当任务工作时,不确定ProgressIndicator应该可见,以向用户显示存在正在运行的Task.当任务暂停时,不应显示ProgressIndicator.

这是我的解决方案:

public class JavaFxTest7 extends Application {

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

    @Override
    public void start(Stage stage) {
        var indicator = new ProgressIndicator();
        indicator.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
        var vBox = new VBox(indicator);
        var scene = new Scene(vBox, 300, 200);
        stage.setScene(scene);
        stage.show();

        Task<Boolean> task = new Task<Boolean>() {
            @Override
            protected Boolean call() throws Exception {
                while(!isCancelled()) {
                    this.updateValue(true);
                    for (long l = 1; l < 150000L; l++) {
                        System.out.println("Working");
                    }
                    System.out.println("Pause");
                    this.updateValue(false);
                    Thread.sleep(2500);
                }
                return null;
            }
        };
        indicator.visibleProperty().bind(task.valueProperty());
        new Thread(task).start();
    }

}

此代码按预期工作,并完成了我需要的一切.然而,我不喜欢这个解决方案,因为它不符合逻辑.我用任务值来控制指标的可见性,效果不好.我想将监听器添加到Task个状态属性,但据我所知,我无法控制状态.

对于这样的问题有更好的解决方案吗?也许我应该使用Service而不是Task

推荐答案

不幸的是,您无法通过state属性做到这一点.Task API不提供设置该属性的方法.尽管即使您可以设置它,但没有一个enum常数似乎能正确地表达"暂停"的含义.

为了避免通过value属性实现这一点,您可以创建自己的Task子集,以公开新的"暂停"布尔属性.然后您只需确保仅更新JavaFX Application Thread上的该属性即可.以下是一个示例,其中对属性的更新是以与Task将更新合并为titlemessageprogressvalue相同的方式合并的.

import java.util.concurrent.atomic.AtomicReference;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.concurrent.Task;

public abstract class PauseableTask<T> extends Task<T> {

  private final ReadOnlyBooleanWrapper paused = new ReadOnlyBooleanWrapper(this, "paused");
  private void setPaused(boolean paused) { this.paused.set(paused); }
  public final boolean isPaused() { return paused.get(); }
  public final ReadOnlyBooleanProperty pausedProperty() {
    return paused.getReadOnlyProperty();
  }

  private final AtomicReference<Boolean> pausedConflater = new AtomicReference<>();

  protected final void updatePaused(boolean paused) {
    if (Platform.isFxApplicationThread()) {
      setPaused(paused);
    } else if (pausedConflater.getAndSet(paused) == null) {
      Platform.runLater(() -> setPaused(pausedConflater.getAndSet(null)));
    }
  }
}

Java相关问答推荐

内容处置 destruct 了PSP请求

Spring Boot找不到Mapper bean

收听RDX中用户数据的变化

Android -如何修复Java.time.zone. ZoneRulesExcept:未知时区ID:Europe/Kyiv

如何使用CSS为选定但未聚焦的表格行设置背景 colored颜色 ?

为什么我的画布没有显示在PFA应用程序中?

Java JAR环境(JRE)是否支持模块?

是否保证在事务性块的末尾标记违反约束?

对运行在GraalVM-21上的JavaFX应用程序使用分代ZGC会警告不支持JVMCI,为什么?

为什么一个Test的instance?& gt;在构造函数中接受非空对象?

Spring Boot Maven包

为什么Java Annotation接口覆盖对象类中的方法

每次FXMLLoader调用ApplationConext.getBean(类)时创建@Component的新实例

为什么同步数据块无效?

一对多关系和ID生成

从12小时开始的日期模式

在Oracle中调用输出参数在索引处缺少IN或OUT参数的函数

Bash数组的单引号元素并使用空格连接

当我将JTextField的getText函数与相等的String进行比较时;t返回true

如何使用我的RLE程序解决此问题