JavaFX的抓屏在OSX无头例外 [英] JavaFX screencapture headless exception on OSX

查看:137
本文介绍了JavaFX的抓屏在OSX无头例外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是从摆动转换我的旧的Java应用程序来JavaFX和我遇到的一个问题。

I'm converting my old java app from swing to javafx and I'm running into a problem.

我用下面的code捕捉到的截图:

I'm using the following code to capture screenshots:

 public ScreenCapper() {
    ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    gs = ge.getScreenDevices();

    try {
        robot = new Robot(gs[gs.length-1]);
    } catch (AWTException e) {
        LOGGER.getInstance().ERROR("Error creating screenshot robot instance!");
    }
}

public Color capture() {
    Rectangle bounds;

    mode = gs[0].getDisplayMode();
    bounds = new Rectangle(0, 0, mode.getWidth(), mode.getHeight());
    //......
}

运行Windows下的应用程序时,此工作正常。然而,在出现以下情况例外OSX下运行时:

This works fine when running the application under Windows. However when running under OSX in get the following exception:

Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:403)
at com.sun.javafx.application.LauncherImpl.access$000(LauncherImpl.java:47)
at com.sun.javafx.application.LauncherImpl$1.run(LauncherImpl.java:115)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.awt.HeadlessException
at sun.java2d.HeadlessGraphicsEnvironment.getScreenDevices(HeadlessGraphicsEnvironment.java:72)
at be.beeles_place.roggbiv.utils.ScreenCapper.<init>(ScreenCapper.java:33)
at be.beeles_place.roggbiv.modes.AverageColorMode.start(AverageColorMode.java:31)
at be.beeles_place.roggbiv.modes.ColorModeContext.startCurrentColorMode(ColorModeContext.java:28)
at be.beeles_place.roggbiv.controller.RoggbivController.<init>(RoggbivController.java:42)
at be.beeles_place.roggbiv.RoggbivMain.start(RoggbivMain.java:67)
at com.sun.javafx.application.LauncherImpl$5.run(LauncherImpl.java:319)
at com.sun.javafx.application.PlatformImpl$5.run(PlatformImpl.java:215)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:179)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:176)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:176)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:76)

这我觉得有待办事项使用JavaFX运行appearently是OSX无头模式,如下面的调试警告提示:

This I think has todo with javafx appearently running is headless mode on OSX, as the following debug warnings suggest:

013-03-10 10:44:03.795 java[1912:5903] *** WARNING: Method userSpaceScaleFactor in class NSView is deprecated on 10.7 and later. It should not be used in new applications. Use convertRectToBacking: instead. 
2013-03-10 10:44:05.472 java[1912:707] [JRSAppKitAWT markAppIsDaemon]: Process manager already initialized: can't fully enable headless mode.

有没有办法得到这个工作?或另一种方式来捕获不与OSX冲突截图?

Is there any way to get this to work? Or another way to capture screenshots that does not conflict with OSX?

满code @ https://github.com/beele/Roggbiv

推荐答案

JavaFX的不使用AWT栈,因此它没有被纯粹JavaFX应用程序启动。由于线程处理细节AWT在Mac上的无头模式,然后从JavaFX的要求正在运行。

JavaFX doesn't use AWT stack, so it's not being started in pure JavaFX application. Due to threads handling specifics AWT is being run in headless mode on Mac then requested from JavaFX.

有下一个选项,以解决:​​

There are next options to solve that:


  1. 使用各种巧妙的初始化AWT - 静态初始化运行 java.awt.Toolkit.getDefaultToolkit(); 修改这只曾在年长的JavaFX,不好意思

  1. Use some voodoo magic to initialize AWT -- in static initialization run java.awt.Toolkit.getDefaultToolkit(); EDIT this worked only in older JavaFX, sorry

更好的选择是退出使用AWT程序,通过JavaFX的。您可以使用旁边的功能,使游戏画面:<一href=\"http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html#snapshot%28javafx.util.Callback,%20javafx.scene.SnapshotParameters,%20javafx.scene.image.WritableImage%29\" rel=\"nofollow\">http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html#snapshot%28javafx.util.Callback,%20javafx.scene.SnapshotParameters,%20javafx.scene.image.WritableImage%29

Better options would be to opt out of using AWT from JavaFX. You can use next functionality to make screenshots: http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html#snapshot%28javafx.util.Callback,%20javafx.scene.SnapshotParameters,%20javafx.scene.image.WritableImage%29

修改亚历山大指出的另一种方式是在一个单独的虚拟机上运行AWT code。为了实现这一目标可以重构的截图功能,一个单独的类和程序,通过JavaFX应用程序调用它:

EDIT As Alexander pointed out another way is to run AWT code in a separate VM. To achieve that you can refactor your screenshot functionality to a separate class and call it from JavaFX app by:

    new ProcessBuilder(
          System.getProperty("java.home") + "/bin/java", 
          "-cp", "classpath", 
          "my.apps.DoScreenshot"
    ).start();

此应用程序可以截图存储到文件系统。
如果你需要经常做的截图,并会见了性能问题,你可以一次运行单独的应用程序,并通过插座与它沟通。

This app can store screenshot to a filesystem. If you need to do screenshots often and met performance issues you can run that separate app once and communicate with it through socket.

使用 com.sun.glass.ui.Robot 而不是 AWTRobot

这篇关于JavaFX的抓屏在OSX无头例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆