在几个任务中修饰几个图像

时间:2016-10-05 09:15:07

标签: javafx javafx-8 executorservice multitasking

一般性:关于我的计划及其运作的解释

我正在制作一张照片修饰的JavaFX应用程序。最终用户可以加载多个图像。当他点击REVERSE按钮时,使用Task为每个图像启动Executor。这些Task中的每一个都执行反转算法:它填充ArrayBlockingQueue<Pixel>(使用add方法)。

当最终用户点击按钮REVERSE时,正如我所说,这些Task已启动。但是在这些语句之后,我告诉JavaFX应用程序线程绘制Pixel的{​​{1}}(使用ArrayBlockingQueue<Pixel>方法)。

因此,JavaFX应用程序线程与remove之间以及ArrayBlockingQueue<Pixel>之间存在并行性和并发性(由Task解决)。

要绘制Task的{​​{1}},JavaFX应用程序线程将启动Pixel。后者包含前面提到的ArrayBlockingQueue<Pixel>方法。为每个图像启动此AnimationTimer。 我想你自己想知道这个remove如何知道它所删除的AnimationTimer属于什么图像?实际上,每个AnimationTimer都有一个属性Pixel,用于指定图像的属性。

我的问题

告诉我,如果我错了,但我的计划应该有效。确实:

  1. 我的JavaFX应用程序线程是唯一更改GUI的线程(在JavaFX中是必需的):Pixel只是进行计算。
  2. 由于我使用的writable_image(特别是没有排水的可能性),因此没有并发性。
  3. Task知道每个BlockingQueue属于哪个图片。
  4. 然而,它(显然!)并非如此(否则我不会创建这个问题哈哈!)。

    我的问题是我的JavaFX应用程序冻结(第一个问题),在绘制了仅一些反转像素(不是所有像素)之后。此外,在最后加载的图片上(第三个问题)。

    可能是问题的原因

    但我需要你的意见。

    AnimationTimer当然不能直接绘制每个图像的反转像素:这是动画的。最终用户可以一点一点地看到图像的每个像素被反转。它在其他算法中非常实用,因为用户可以“查看”算法的工作原理。

    但要做到这一点,Pixel需要读取一个名为AnimationTimer的变量。此变量在... AnimationTimer中被修改(写入)。但它是max。所以如果我不错Task本身之间或JavaFX应用程序线程与这些AtomicLong之间没有任何并发​​问题。

    然而,问题可能是:Task n°1(=图像编号1)中Task的值可能为2000,max中的值为59 } n°2(=图像n°2)。问题是Task对于图像n°1必须使用2000,对于n°2必须使用59。但是如果Task n°1 et n°2已经完成,AnimationTimer已知的唯一值将是59 ...

    来源

    当用户点击按钮REVERSE

    我们启动了多个Task并开始了几次 AnimationTimer。 CLASS:RightPane.java

    Task

    AnimationTimer是CLASS GraphicEngine的一部分,其中包含WritableImage current_writable_image; for(int i = 0; i < this.gui.getArrayListImageViewsImpacted().size(); i++) { current_writable_image = (WritableImage) this.gui.getArrayListImageViewsImpacted().get(i).getImage(); this.gui.getGraphicEngine().executor.execute(this.gui.getGraphicEngine().createTask(current_writable_image)); } for(int i = 0; i < this.gui.getArrayListImageViewsImpacted().size(); i++) { current_writable_image = (WritableImage) this.gui.getArrayListImageViewsImpacted().get(i).getImage(); this.gui.getImageAnimation().setWritableImage(current_writable_image); this.gui.getImageAnimation().startAnimation(); }

    Task

    相同的CLASS,GraphicEngine,也包含反转算法:

    Executor

    最后,这是CLASS public final Executor executor = Executors.newCachedThreadPool(runnable -> { Thread t = new Thread(runnable); t.setDaemon(true); return t ; }); public Task createTask(WritableImage writable_image) { int image_width = (int) writable_image.getWidth(), image_height = (int) writable_image.getHeight(); Task ret = new Task() { protected Void call() { switch(operation_to_do) { case "reverse" : gui.getImageAnimation().setMax(image_width*image_height); // USE OF "MAX" VARIABLE reverseImg(writable_image); break; } return null; } }; return ret; } 的代码。没有什么特别的。请注意,此处也使用变量private void reverseImg(WritableImage writable_image) { int image_width = (int) writable_image.getWidth(), image_height = (int) writable_image.getHeight(); BlockingQueue<Pixel> updates = gui.getUpdates(); PixelReader pixel_reader = writable_image.getPixelReader(); double[] rgb_reversed; for (int x = 0; x < image_width; x++) { for (int y = 0; y < image_height; y++) { rgb_reversed = PhotoRetouchingFormulas.reverse(pixel_reader.getColor(x, y).getRed(), pixel_reader.getColor(x, y).getGreen(), pixel_reader.getColor(x, y).getBlue()); updates.add(new Pixel(x, y, Color.color(rgb_reversed[0], rgb_reversed[1], rgb_reversed[2], pixel_reader.getColor(x, y).getOpacity()), writable_image)); } } } (以及CLASS AnimationTimermax)。

    GraphicEngine

0 个答案:

没有答案