java - How can I use JavaFX Canvas from within a web server without running the FX Application thread - Stack Overflow

I am running a Javalin web server and want to create an algorithmic image with JavaFX Canvas and serve

I am running a Javalin web server and want to create an algorithmic image with JavaFX Canvas and serve that over http. So far I have created a new Canvas and embedded it inside a Stage and it works fine. But when I try to use the Canvas standalone from the webserver thread as follows:

    public byte[] getResponse() throws IOException {
      WritableImage snapshot = new FlowersFX(width, height).draw().getCanvas().snapshot(null, null);
      ByteArrayOutputStream stream = new ByteArrayOutputStream();
      ImageIO.write(SwingFXUtils.fromFXImage(snapshot, null), "png", stream);
      return stream.toByteArray();
    }

I get java.lang.IllegalStateException:

java.lang.IllegalStateException: Not on FX application thread; currentThread = JettyServerThreadPool-33
at [email protected]/com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:294)
at [email protected]/com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:481)
at [email protected]/javafx.scene.Node.snapshot(Node.java:2255)
at StaticImager/top.bagadbilla.handler.FlowerGeneratorHandler.getResponse(FlowerGeneratorHandler.java:35)
at StaticImager/top.bagadbilla.App.lambda$run$8(App.java:55)

I have tried running Platform.startup() before running the server and then creating and updating the canvas inside Platform.runLater() but the thread just freezes indefinitely, and I dont like having to run another thread when a separate thread is created by the webserver anyway.

EDIT: Here is the code when using Platform.runLater to run the canvas in application fx thread and it keeps on waiting for future.get():

public class FlowerGeneratorHandler {
private Canvas canvas;
private final RunnableFuture<Void> future;
public FlowerGeneratorHandler(int width, int height) {
    Runnable runnable = () -> canvas = new FlowersFX(width, height).draw().getCanvas();
    future = new FutureTask<>(runnable, null);
    Platform.runLater(future);
}

public byte[] getResponse() throws IOException, ExecutionException, InterruptedException {

    future.get();
    WritableImage snapshot = canvas.snapshot(null, null);
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    ImageIO.write(SwingFXUtils.fromFXImage(snapshot, null), "png", stream);
    return stream.toByteArray();
}

}

and Platform is started before:

        Javalin.create()
            .events(eventConfig -> {
                eventConfig.serverStarting(() -> Platform.startup(() -> {
                    System.out.println("Starting platform");
                }));
                eventConfig.serverStopping(Platform::exit);
            })
    .....

EDIT2: Changed future being passed on as Runnable to Platform.runLater(), but the original exception is back java.lang.IllegalStateException: Not on FX application thread; currentThread = JettyServerThreadPool-33

EDIT3: turns out canvas.snapshot() call needs to be on the FX Application thread. Working fine after moving it inside runnable as well.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744999528a4605407.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信