当前位置: 首页 > 知识库问答 >
问题:

完成后在JavaFX中再次运行相同的任务

公西俊才
2023-03-14

我试着为家庭锻炼建立一个倒计时器,它在相同的间隔下运行两次,然后给你一个额外的间隔Rest。之后,它应该重新开始与3个间隔。

目前,我正在成功地运行从30秒到零的第一个间隔。我的问题是,我不能确定JavaFX任务是否完成。更准确地说,如果不创建几个自覆盖进程(例如,使用for循环),我就无法重新开始使用它。

这是我的controller.class用于处理我的FXML文件:

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Slider;


public class Controller {

private int time;

@FXML
private Label counterLabel;

private static StringProperty displayTime = new SimpleStringProperty("30");

@FXML
private Button startstop;

@FXML
private ProgressIndicator progress;

private static DoubleProperty prog = new SimpleDoubleProperty(0.0);

@FXML
private Slider Pausendauer; // pause length

@FXML
private Slider Trainingsdauer; //interval length

@FXML
private Slider Repeats;

public void initialize() {
    progress.setProgress(0);
    counterLabel.textProperty().bind(displayTime);
    progress.progressProperty().bind(prog);
}


public void click(ActionEvent e) throws InterruptedException {
    //event for clicking start button

    //Task for Counting (Should be repeatable after running through
        time = (int)Trainingsdauer.getValue();
            Task<String> count = new TaskTimer(time);
            displayTime.bind(count.valueProperty());
            prog.bind(count.progressProperty());
            count.run();
    }
}
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javafx.concurrent.Task;


public class TaskTimer extends Task<String>{

    private int time;
    double fraction;
    double prog;
    public static void main(String[] args) {
    }

    public TaskTimer(int sec) {
        this.time = sec;
        this.fraction = 1.0 / time; //claculating for closng circle
        this.prog = 0.0;
    }

    protected String call() throws Exception {
        // TODO Auto-generated method stub
        //runs scheduled without delay
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
            scheduler.scheduleAtFixedRate(new Runnable(){
            public void run() {
                time = time - 1; //Decrement of time
                prog = prog + fraction; //increase progress
                updateProgress(prog, 1);

                if(time >= 10) { // Makes 01 from 1 and so on
                updateValue(time+"");
                }else {
                updateValue("0"+time);
                }
                System.out.println(time+"");


                if (time <= 0) {
                    updateProgress(1, 1);
                    scheduler.shutdown();
                }
            }

            }, 1, 1, TimeUnit.SECONDS);

            return time+"";

        }
    }

描述功能的GUI设计

接下来我可以尝试什么?已经尝试了一大堆东西了。我的大多数“解决方案”最终都是自我覆盖双胞胎和一个冻结的UI。

共有1个答案

毋炳
2023-03-14

您可以使用Task.SetonSucceed方法来构造和调用新的任务,如下所示:

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class RestartProgressIndicator extends Application {

    private static int COUNT_DOWN = 10;
    @Override
    public void start(Stage stage) {

        Work work = new Work();
        Button button = new Button("Go");
        button.setDefaultButton(true);
        button.setOnAction(e -> {
            work.work(COUNT_DOWN);
            button.setDisable(true);
        });

        Pane root = new BorderPane(null,work.getPane(),null, button,null);
        root.setPadding(new Insets(20.));
        Scene scene = new Scene(root, Color.WHITE);
        stage.setScene(scene);
        stage.centerOnScreen();
        stage.show();
    }

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

class Work{

    private TaskTimer count;
    private final ProgressIndicator pi;
    private final Pane pane;
    private int counter = 0;

    Work(){
        pi = new ProgressIndicator();
        pi.setMinWidth(150);  pi.setMinHeight(150);
        pane = new Pane(pi);
    }

    void work(int seconds){

        count = new TaskTimer(seconds);
        pi.progressProperty().bind(count.progressProperty());

        count.setOnSucceeded(e->{
            pi.progressProperty().unbind();
            if(isRestarart()) {
                work(seconds);
            }
        });

        Thread th = new Thread(count);
        th.setDaemon(true);
        th.start();
    }

    private boolean isRestarart() {
        // TODO apply restart logic
        return ++counter < 3;
    }

    Pane getPane() {
        return pane;
    }
}

class TaskTimer extends Task<String>{

    private final int seconds;
    double fraction, prog;

    public TaskTimer(int seconds) {
        this.seconds = seconds;
        fraction = 1.0 / seconds;
        prog = 0.0;
    }

    @Override
    protected String call() throws Exception {

        int time = seconds;
        while(true){
            time = time - 1; //Decrement of time
            prog = prog + fraction; //increase progress
            updateProgress(prog, 1);

            if(time >= 10) { // Makes 01 from 1 and so on
                updateValue(time+"");
            }else {
                updateValue("0"+time);
            }

            TimeUnit.SECONDS.sleep(1);

            if (time <= 0) {
                updateProgress(1, 1);
                break;
            }
        };

        return time+"";
    }
}
 类似资料:
  • 问题内容: 我想在pullData()完成后运行loadViews(),但我想知道这样做的最佳方法是什么?我也想在其上设置10秒超时,以便在可能的情况下显示网络错误。根据我的阅读,GCD看起来是完成此任务的方法,但是我对它的实现感到困惑。谢谢你提供的所有帮助! 问题答案: 您需要的是带有完成块的完成处理程序。 创建它非常简单: 并使用您的完成块,如下所示:

  • 比如说有个需求, 任务1执行完成了, 将数据存到数据库了, 然后立马要开启下一个任务, 获取所有的数据和其他表的数据进行清洗, 然后存到另一个表里 第一个任务是从kafka里获取的增量数据, 然后直接存到库里, flink执行起来就是source -> sink -> execute 这时候第一个任务完成了, 要开启第二个任务了, 需要从数据库里获取新的数据和其他表的数据进行清洗 source -

  • 我运行了一个线程来更新应用程序的打开时间。效果很好。我扩大了服务级别。从这个任务开始的时间会按平台更新我的GUI文本字段。朗奈特 我想运行第二个线程来更新GUI。我不能跑同一条线。两个独立的线程可以在GUI上更新吗?互联网上的大部分信息都集中在一个主题上。谢谢你的建议

  • 问题内容: 如果用户到达程序末尾,我希望他们得到一个提示,询问他们是否要重试。如果他们回答是,我想重新运行该程序。 问题答案: 您可以将整个程序放在另一个while循环中,该循环询问用户是否要重试。

  • 问题内容: 因此,我一直在尝试Gulp,看看它在速度上与Grunt相比如何,我对结果印象深刻,但是我有一件事我不知道如何在Gulp中进行。 因此,我有这个任务来缩小HTML: buildMetaData对象具有我需要的自定义功能,以及为什么不能使用像gulp- changed这样的插件。我要弄清楚的是,在缩小完成后如何(如果可能)运行代码块来处理所有文件并成功运行。gulp有可能发生这种情况吗?

  • 问题内容: 在下面,该语句在调用完成 之前 被执行。我该如何更改? 问题答案: 您不能-至少不明智。虽然可以在jQuery ajax请求上设置一个属性,但过去在尝试将其与值一起使用时遇到了 严重的问题。 尝试重新考虑您要完成的工作: 然后: 或者,如果您的回调 仅 需要访问返回的数据,那么您可以更简单地执行 然后