在方法内更新JavaFX舞台。

huangapple go评论77阅读模式
英文:

Update JavaFX stage within method

问题

我正在编写一个程序需要使用大量数据进行多次计算而且需要一段时间才能完成这就是为什么我想要更新并通知用户程序当前已完成的百分比但是我不知道如何在计算方法内部更新阶段

public void calculate() {
    // 在这里我想要更改“百分比文本”
    // 并更新舞台。
}
英文:

I am writing a program that uses a lot of data to do several calculations and it takes quite a while to finish. This is why I want to update and inform the user on the current percentage of the program being done. However I don't know how I can update the stage within the calculation method.

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
 
public class Main extends Application {
	
    public void calculate() {
    	//Here I want to change the "percentage text"
    	//and update the stage.
    }
    
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Hello World!");
        
        Text percentage = new Text();
        
        Button btn = new Button();
        btn.setText("Say 'Hello World'");
        btn.setOnAction(new EventHandler<ActionEvent>() {
 
            @Override
            public void handle(ActionEvent event) {
                calculate();
            }
        });
        
        final GridPane inputGridPane = new GridPane();
        GridPane.setConstraints(btn, 0, 0);
        GridPane.setConstraints(percentage, 1, 0);
        inputGridPane.setHgap(6);
        inputGridPane.setVgap(6);
        inputGridPane.getChildren().addAll(btn, percentage);
        
        final Pane rootGroup = new VBox(12);
        rootGroup.setPrefWidth(400);
        rootGroup.setPrefHeight(225);
        rootGroup.getChildren().addAll(inputGridPane);
        rootGroup.setPadding(new Insets(12,12,12,12));
        
        primaryStage.setScene(new Scene(rootGroup));
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

This is what my code roughly looks like. Thank you in advance.

答案1

得分: 0

JavaFx提供了一个名为"Task<v>"的类,可以用于在后台进行计算并保持进度同步!

我建议这样做:

创建一个继承Task<v>的第二个类来执行重计算:

import javafx.concurrent.Task;

public class CalculationTask extends Task&lt;String&gt; {
    @Override
    protected String call() throws Exception {
        for (int i = 0; i &lt; 100000000;i++) {
            updateProgress(i, 100000000);
        }

        succeeded();
        return "这是计算的结果... 如果你在计算数字,数据类型可以通过泛型进行更改";
    }
}

这是在应用程序类中如何使用它的一种方式:

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Hello World!");

        Button btn = new Button();
        btn.setText("Say 'Hello World'");

        Task&lt;String&gt; calculationTask = new CalculationTask();

        ProgressBar progressBar = new ProgressBar(); //ProgressIndicator could also be used
        progressBar.progressProperty().bind(calculationTask.progressProperty());
        progressBar.visibleProperty().bind(calculationTask.runningProperty());

        btn.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
            @Override
            public void handle(ActionEvent event) {
                calculationTask.setOnSucceeded(new EventHandler&lt;WorkerStateEvent&gt;() {
                    @Override
                    public void handle(WorkerStateEvent workerStateEvent) {
                        new Alert(Alert.AlertType.CONFIRMATION, calculationTask.getValue()).show();
                    }
                });
                new Thread(calculationTask).start();
            }
        });

        final GridPane inputGridPane = new GridPane();
        GridPane.setConstraints(btn, 0, 0);
        GridPane.setConstraints(progressBar, 1, 0);
        inputGridPane.setHgap(6);
        inputGridPane.setVgap(6);
        inputGridPane.getChildren().addAll(btn, progressBar);

        final Pane rootGroup = new VBox(12);
        rootGroup.setPrefWidth(400);
        rootGroup.setPrefHeight(225);
        rootGroup.getChildren().addAll(inputGridPane);
        rootGroup.setPadding(new Insets(12,12,12,12));

        primaryStage.setScene(new Scene(rootGroup));
        primaryStage.show();
    }

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

希望这有所帮助,否则请随时提问!

英文:

JavaFx provides a class called "Task<v>" which can be used for background calculations while keeping the progression syncronised!

I would suggest doing it that way:

Create a second class extending Task<v> for doing the heavy calculation:

import javafx.concurrent.Task;
public class CalculationTask extends Task&lt;String&gt; {
@Override
protected String call() throws Exception {
for (int i = 0; i &lt; 100000000;i++) {
updateProgress(i, 100000000);
}
succeeded();
return &quot;This is the computed result... Datatype can be changed by generics if you are calculation numbers&quot;;
}
}

This is one way how you could use it in your application class:

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Dialog;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle(&quot;Hello World!&quot;);
Button btn = new Button();
btn.setText(&quot;Say &#39;Hello World&#39;&quot;);
Task&lt;String&gt; calculationTask = new CalculationTask();
ProgressBar progressBar = new ProgressBar(); //ProgressIndicator could also be used
progressBar.progressProperty().bind(calculationTask.progressProperty());
progressBar.visibleProperty().bind(calculationTask.runningProperty());
btn.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
@Override
public void handle(ActionEvent event) {
calculationTask.setOnSucceeded(new EventHandler&lt;WorkerStateEvent&gt;() {
@Override
public void handle(WorkerStateEvent workerStateEvent) {
new Alert(Alert.AlertType.CONFIRMATION, calculationTask.getValue()).show();
}
});
new Thread(calculationTask).start();
}
});
final GridPane inputGridPane = new GridPane();
GridPane.setConstraints(btn, 0, 0);
GridPane.setConstraints(progressBar, 1, 0);
inputGridPane.setHgap(6);
inputGridPane.setVgap(6);
inputGridPane.getChildren().addAll(btn, progressBar);
final Pane rootGroup = new VBox(12);
rootGroup.setPrefWidth(400);
rootGroup.setPrefHeight(225);
rootGroup.getChildren().addAll(inputGridPane);
rootGroup.setPadding(new Insets(12,12,12,12));
primaryStage.setScene(new Scene(rootGroup));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

I hope that helped, otherwise feel free to ask questions!

huangapple
  • 本文由 发表于 2020年7月22日 17:25:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63031026.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定