gpt4 book ai didi

JavaFX : updating progress for the multiple tasks

转载 作者:搜寻专家 更新时间:2023-10-31 19:47:55 25 4
gpt4 key购买 nike

我正在使用 JavaFX 2.2 编写多线程分形绘图程序,现在我需要一些指导。

我想要实现的是创建一个任务或服务(尚未决定),然后启动一些其他任务,这些任务实际执行计算并在准备就绪时返回整个图像的部分。当所有部分都返回到启动任务时,它会将这些部分放在一起并将其返回到主线程,以便可以将其可视化。

显然,所有这一切都必须在不阻塞 UI 的情况下发生。

问题是我无法弄清楚这些任务如何相互通信。例如,我需要根据其中任务的平均进度(或类似的东西)更新启动任务的进度属性,因此它们的进度属性应该以某种方式绑定(bind)到启动任务的进度属性。图像片段应放在列表或某个容器中,并在所有图像都可用时在单独的图像上重新绘制。

我已经为该程序编写了一个更简单(尽管仍处于实验阶段)的版本,它只创建了一个计算整个分形的任务。进度绑定(bind)到 GUI 的 progressBar。任务成功时,返回值由 EventHandler 处理。

我不要求一个完整的解决方案,但一些想法和一些示例代码可能真的对我有帮助。

这是应该修改的类:

package fractal;

import fractalUtil.DefaultPalette;
import fractalUtil.PaletteInterface;
import javafx.concurrent.Task;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import org.apache.commons.math3.complex.Complex;

/**
*
* @author athelionas
*/
public abstract class AbstractFractal extends Task implements FractalInterface {

private PaletteInterface palette;
protected final int width, height, order, iterations;
protected final double scale, xReal, xIm, xCenter, yCenter, zoom;
protected final boolean julia;

protected AbstractFractal(final int width, final int height, final double xReal, final double xIm, final double xCenter, final double yCenter, final int order, final boolean julia, final int iterations, final double zoom) {
this.width = width;
this.height = height;
this.xReal = xReal;
this.xIm = xIm;
this.xCenter = xCenter;
this.yCenter = yCenter;
this.order = order;
this.julia = julia;
this.iterations = iterations;
this.zoom = zoom;
this.scale = (double) width / (double) height;
palette = new DefaultPalette();
}

@Override
public final void setPalette(final PaletteInterface palette) {
this.palette = palette;
}

@Override
public abstract Complex formula(final Complex z, final Complex c, final int order, final Complex center);

@Override
public final Color calculatePoint(final Complex z, final Complex c, final int order, final Complex center, final int iterations) {
Complex zTemp = z;
int iter = iterations;
while (zTemp.abs() <= 2.0 && iter > 0) {
zTemp = formula(zTemp, c, order, center);
iter--;
}
if (iter == 0) {
return Color.rgb(0, 0, 0);
} else {
return palette.pickColor((double) (iterations - iter) / (double) iterations);
}
}

@Override
public final WritableImage call() {
Complex z;
Complex c;
Complex center = new Complex(xCenter, yCenter);
final WritableImage image = new WritableImage(width, height);

if (julia) {
c = new Complex(xReal, xIm);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {

z = new Complex(((double) x) / (double) (width - 1) * 2.0 * scale * (1.0 / zoom) - scale * (1.0 / zoom), ((double) y) / (double) (height - 1) * 2.0 * (1.0 / zoom) - 1.0 * (1.0 / zoom));

image.getPixelWriter().setColor(x, y, calculatePoint(z, c, order, center, iterations));
}

}
} else {
z = new Complex(xReal, xIm);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {

c = new Complex(((double) x) / (double) (width - 1) * 2.0 * scale * (1.0 / zoom) - scale * (1.0 / zoom), ((double) y) / (double) (height - 1) * 2.0 * (1.0 / zoom) - 1.0 * (1.0 / zoom));

image.getPixelWriter().setColor(x, y, calculatePoint(z, c, order, center, iterations));
}
updateProgress(y, height);
}
}
return image;
}
}

最佳答案

使用绑定(bind)和任务。这样你根本不需要关心线程。您所需要的只是创建一个绑定(bind),该绑定(bind)将根据线程数规范化每个进度并汇总它们。例如

progressBar.progressProperty().bind(
task1.progressProperty().multiply(0.5).add(
task2.progressProperty().multiply(0.5)));

对于未知数量的线程来说有点棘手。看下一个例子:

public class MultiProgressTask extends Application {
private static final int THREADS_NUM = 10;

// this is our Task which produces a Node and track progress
private static class MyTask extends Task<Node> {

private final int delay = new Random().nextInt(1000) + 100;
{ System.out.println("I update progress every " + delay); }

@Override
protected Node call() throws Exception {
updateProgress(0, 5);
for (int i = 0; i < 5; i++) {
System.out.println(i);
Thread.sleep(delay); // imitating activity
updateProgress(i+1, 5);
}
System.out.println("done");
return new Rectangle(20, 20, Color.RED);
}
};

@Override
public void start(Stage primaryStage) {
ProgressBar pb = new ProgressBar(0);
pb.setMinWidth(300);

final VBox root = new VBox();
root.getChildren().add(pb);

Scene scene = new Scene(root, 300, 250);

primaryStage.setScene(scene);
primaryStage.show();

DoubleBinding progress = null;

for (int i = 0; i < THREADS_NUM; i++) {
final MyTask mt = new MyTask();

// here goes binding creation
DoubleBinding scaledProgress = mt.progressProperty().divide(THREADS_NUM);
if (progress == null) {
progress = scaledProgress;
} else {
progress = progress.add(scaledProgress);
}
// here you process the result of MyTask
mt.setOnSucceeded(new EventHandler<WorkerStateEvent>() {

@Override
public void handle(WorkerStateEvent t) {
root.getChildren().add((Node)t.getSource().getValue());
}
});
new Thread(mt).start();
}
pb.progressProperty().bind(progress);
}


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

关于JavaFX : updating progress for the multiple tasks,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12986916/

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