Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于服务器端映像生成的JavaFX_Java_Spring_Image Processing_Javafx 2_Javafx - Fatal编程技术网

用于服务器端映像生成的JavaFX

用于服务器端映像生成的JavaFX,java,spring,image-processing,javafx-2,javafx,Java,Spring,Image Processing,Javafx 2,Javafx,这听起来很奇怪,但我想使用JavaFX在服务器端生成图表图像。因为JavaFX有很好的画布API来执行图像转换、连接和定位 特别是,我有一个SpringMVC服务来将图表生成为图像。 主要问题是如何从方便的Springbean调用JavaFXAPI。 如果我尝试从java应用程序运行javafx代码(不扩展javafx应用程序类),我会得到 您对如何解决这个问题有什么建议/想法吗?也许类似的解决方案会有所帮助 否则,我会考虑创建一个服务并将图像推送到数据存储区并在Spring应用程序中检索它。

这听起来很奇怪,但我想使用JavaFX在服务器端生成图表图像。因为JavaFX有很好的画布API来执行图像转换、连接和定位

特别是,我有一个SpringMVC服务来将图表生成为图像。 主要问题是如何从方便的Springbean调用JavaFXAPI。 如果我尝试从java应用程序运行javafx代码(不扩展javafx应用程序类),我会得到


您对如何解决这个问题有什么建议/想法吗?

也许类似的解决方案会有所帮助

否则,我会考虑创建一个服务并将图像推送到数据存储区并在Spring应用程序中检索它。


希望至少能提供一点帮助

经过一些研究,我用JavaFX实现了画布绘制,下面是一个简化的示例:

首先,我制作了JavaFX应用程序,该应用程序将在单独的线程中启动(我使用Spring taskExecutor,但可以使用普通java线程)

然后,当Spring应用程序启动时,我调用initialize()方法:

@Autowired private TaskExecutor taskExecutor;

@PostConstruct private void initChartGenerator() {
    ChartGenerator.initialize(taskExecutor);
}
此cource解决方案可以移植到非Spring应用程序

这是一个单线程解决方案(在我的例子中已经足够了),但我认为它可以用于多线程使用(可能使用RMI调用draw方法)

此外,此解决方案在我的windows工作站上“按原样”工作,但在linux服务器环境中,应调用一些其他操作:

  • 您不能在OpenJDK上使用JavaFX(截至2013年8月)-必须切换到Oracle JDK
  • Java版本必须不低于Java 7u6
  • 最复杂的是,您必须使用虚拟显示使JavaFX在无头环境中运行:

    apt获取并安装xvfb

    //然后在应用程序服务器上启动:

    导出显示=“:99”

    启动-停止守护进程--启动--后台--用户jetty--exec“/usr/bin/sudo”--u jetty/usr/bin/Xvfb:99-屏幕0 1024x768x24



  • 另外,您还可以使用服务器端的其他JavaFX功能(例如,将html导出到图像)。

    如果其他人正在寻找,这是一种更简单的方法。 使用JavaFX2.2,我能够执行以下操作

        waitForInit = new Semaphore(0);
        root = new Group();
        root.getChildren().add(jfxnode);
        FxPlatformExecutor.runOnFxApplication(() -> {
            snapshot = jfxnode.snapshot(new SnapshotParameters(), null);
            waitForInit.release();
        });
    
        waitForInit.acquireUninterruptibly();
        BufferedImage bi = SwingFXUtils.fromFXImage(snapshot, null);
    
    无需将节点添加到组中。 从那里,您可以对图像执行任何操作

    FxPlatformExecutor来自我在项目中使用的JME3-JFX库。 见:

    您可以轻松创建
    runOnFxApplication()
    方法或创建FxPlatformExecutor类

    这是代码

    package com.jme3x.jfx;
    
    import javafx.application.Platform;
    
    /**
     * TODO This Class should be replaced by some Workmanager implemntation
     * in the future
     * @author Heist
     */
    public class FxPlatformExecutor {
    
        public static void runOnFxApplication(Runnable task) {
            if (Platform.isFxApplicationThread()) {
                task.run();
            } else {
                Platform.runLater(task);
            }
        }
    }
    

    我没有写这段代码,github链接在上面。

    这很酷。我很兴奋能尝试一下。谢谢你的努力!不必在(result==null)时使用
    等待结果,而可以将提交到,如对的答复中所述。使用FutureTask应该更有效率,因为不会有繁忙的等待循环。这是一个不完整的示例,没有引用类FxPlatformExecutor-无法找到。感谢您指出这一点。导入是从我的项目中的第三方库中进行的,请参见。它很容易实现。我将把它添加到答案中。
    
        waitForInit = new Semaphore(0);
        root = new Group();
        root.getChildren().add(jfxnode);
        FxPlatformExecutor.runOnFxApplication(() -> {
            snapshot = jfxnode.snapshot(new SnapshotParameters(), null);
            waitForInit.release();
        });
    
        waitForInit.acquireUninterruptibly();
        BufferedImage bi = SwingFXUtils.fromFXImage(snapshot, null);
    
    package com.jme3x.jfx;
    
    import javafx.application.Platform;
    
    /**
     * TODO This Class should be replaced by some Workmanager implemntation
     * in the future
     * @author Heist
     */
    public class FxPlatformExecutor {
    
        public static void runOnFxApplication(Runnable task) {
            if (Platform.isFxApplicationThread()) {
                task.run();
            } else {
                Platform.runLater(task);
            }
        }
    }