我正在用 JavaFX 2.2 编写一个多线程分形绘图程序,现在我需要一些指导。
我想要实现的是创建一个任务或服务(尚未决定),然后启动其他一些实际执行计算的任务,并在准备好时返回整个图像的部分。当所有的部分都返回到启动任务时,它会将这些部分放在一起并将其返回到主线程,以便可视化。
显然,所有这些都必须在不阻塞 UI 的情况下发生。
问题是我无法弄清楚这些任务如何相互通信。例如,我需要根据其中任务的平均进度(或类似的东西)更新启动任务的进度属性,因此它们的进度属性应该以某种方式绑定到启动任务的进度属性。图像片段应放在列表或某个容器中,并在所有图像都可用时在单独的图像上重绘。
我已经编写了这个程序的一个更简单(尽管仍然是实验性的)版本,它只创建一个计算整个分形的任务。进度绑定到 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;
}
}