Есть канвас, который у которого вызывается repaint в бесконечном цикле. При репаинте канвасу задается случайный цвет.
Ожидание: у канваса должны меняться постоянно цвета, (в данный момент 1 итерация цикла проходит быстро, потом будет обрабатываться около 1-2 секунд).
Реальность: цвет у канваса не обновляется. Если сделать не бесконечный цикл, а конечный - визуально канвас обновится, как только закончится этот цикл.
Как сделать так, что бы канвас обновлялся визуально в процессе цикла?
Ниже показан callback, который вызывается в цикле (метод update() - repaint() + установка цвета перед repaint'ом):
public void redrawCanvas (Color color) {
System.out.println(color.getRed() + ", " + color.getGreen() + ", " + color.getBlue());
this.renderCanvas.update(color);
this.renderWindow.repaint();
}
В консоль выводятся корректные цвета.
UPD: если делать через Timer вместо while вылетает java.util.concurrent.RejectedExecutionException эксепшн, я так понял из за того, что у меня получение рандомного цвета разбросано по потокам, через ExecutorService.
Полный код:
Основной класс - handler клика по кнопке запускает цикл, redrawCanvas - коллбэк, выполняющийся каждый раз, когда получен цвет внутри цикла.
private void renderButtonHandler (ActionEvent event) {
RenderThreadsController renderThreadsController = new RenderThreadsController(this::redrawCanvas);
renderThreadsController.run();
}
public void redrawCanvas (Color color) {
System.out.println(color.getRed() + ", " + color.getGreen() + ", " + color.getBlue());
this.renderCanvas.update(color);
this.renderWindow.repaint();
}
RenderThreadsController.java
thread.get() возвращает массив из 3-х случайных int 0-255
public class RenderThreadsController implements Runnable {
final private int threadsCount = 8;
private ExecutorService executorService;
private List<Future<int[]>> threadsPool;
private int currentSample = 1;
private RedrawCanvas callback;
RenderThreadsController(RedrawCanvas callback) {
Thread thread = new Thread(this);
thread.start();
this.executorService = Executors.newCachedThreadPool();
this.threadsPool = new ArrayList<>();
this.callback = callback;
}
public void run() {
for (int i = 0; i < this.threadsCount; i++) {
this.threadsPool.add(
this.executorService.submit(
new RenderThread(
this.currentSample++
)
)
);
}
int t = 20;
/*while (t > 0) {
this.startThread();
t--;
}*/
while (this.threadsPool.size() > 0) {
this.startThread();
}
executorService.shutdown();
}
private void startThread () {
try {
Future<int[]> thread = this.threadsPool.get(0);
int[] color = thread.get();
this.callback.redrawCanvas(new Color(color[0], color[1], color[2]));
this.threadsPool.remove(0);
this.threadsPool.add(
this.executorService.submit(
new RenderThread(
this.currentSample++
)
)
);
} catch (InterruptedException|ExecutionException e) {
e.printStackTrace();
}
}
}