我正在将旧的 Java 应用程序从 swing 转换为 javafx,但遇到了问题。
我使用以下代码来捕获屏幕截图:
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 下运行时出现以下异常:
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 在 OSX 上运行的 headless 模式有关,如以下调试警告所示:
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 不冲突的截屏方法?
最佳答案
JavaFX 不使用 AWT 堆栈,因此它不会在纯 JavaFX 应用程序中启动。由于线程处理细节,AWT 在 Mac 上以 headless 模式运行,然后从 JavaFX 请求。
有以下选项可以解决这个问题:
使用一些巫毒魔法来初始化 AWT - 在静态初始化中运行
java.awt.Toolkit.getDefaultToolkit();
编辑 这仅适用于较旧的 JavaFX ,抱歉更好的选择是选择不使用 JavaFX 中的 AWT。您可以使用下一个功能来制作屏幕截图:http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html#snapshot%28javafx.util.Callback,%20javafx.scene.SnapshotParameters,%20javafx.scene.image.WritableImage%29
编辑 正如 Alexander 指出的另一种方法是在单独的 VM 中运行 AWT 代码。为了实现这一点,您可以将屏幕截图功能重构为一个单独的类,并通过以下方式从 JavaFX 应用程序调用它:
new ProcessBuilder( System.getProperty("java.home") + "/bin/java", "-cp", "classpath", "my.apps.DoScreenshot" ).start();
这个应用程序可以将屏幕截图存储到文件系统中。 如果您需要经常进行屏幕截图并遇到性能问题,您可以运行该单独的应用程序一次并通过套接字与其进行通信。
使用
com.sun.glass.ui.Robot
而不是AWTRobot
关于OSX 上的 JavaFX 屏幕捕获 headless 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26788965/