2013-03-10 9 views
9

私の古いJavaアプリケーションをswingからjavafxに変換していますが、問題が発生しています。OSXの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の下で実行している場合しかし:

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. 

は、いずれかがあります:

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ランニングでTODOを持っていると思うこれは、OSX上でヘッドレスモードでありますこれを動作させる方法は?あるいは、OSXと矛盾しないスクリーンショットをキャプチャする別の方法は?それは純粋なJavaFXアプリケーションで開始されていないので、https://github.com/beele/Roggbiv

+1

を*なぜ地球上で、それはそれを行うだろう*「私はJavaFXのはappearentlyランニングでTODOを持っていると思うこれはOSX上のヘッドレスモードですか」?これはGUIツールキットであり、スクリーンなしではほとんど使用されません。 –

+0

私は、GraphicsEnvironment.isHeadless()のgithubチェックのコードにチェックを追加して、trueを返します。 – Beele

答えて

6
@

完全なコード

JavaFXのは、AWTのスタックを使用していません。スレッド処理のために、AWTはMacではヘッドレスモードで実行されており、JavaFXからリクエストされています。

それを解決するために、次のオプションがあります。

  1. はAWTを初期化するために、いくつかのブードゥー教の魔法を使用する - 静的初期化実行でjava.awt.Toolkit.getDefaultToolkit();EDITを、これはより良い

  2. 申し訳ありませんが、古いの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

  3. EDITアレクサンダーは、別の方法を指摘したように別のVMでAWTのコードを実行することです。ファイルシステムに格納することができますスクリーンショット

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

    このアプリ:あなたは別のクラスにあなたのスクリーンショット機能をリファクタリングとによってJavaFXのアプリからそれを呼び出すことができることを達成するために。 スクリーンショットを頻繁に実行し、パフォーマンスの問題に遭遇した場合、その別のアプリを一度実行してソケットで通信することができます。

  4. 代わりAWTRobot

+0

オプション1は、起動時に表示される警告を隠しますが、 javafxアプリ全体が画面に表示されません。 オプション2は私が推測するものではありません。インタフェースの一部をイメージにレンダリングします。アプリケーションの一部ではなく、デスクトップ全体をキャプチャする必要があります。 私は今、OS X上で動作させるオプションがないと思います... – Beele

+0

Mac OSでスクリーンショットを撮ることは可能ですが、心配はいりません。答えは存在する。 –

+0

@BeeleどのJavaFXのバージョンを使用しますか? –

3

の使用com.sun.glass.ui.Robot私は注意が必要になることがあり、次のものを参照してください。セルゲイGrinevのポイント1.に加えて

  1. javafx.macosx.embeddedを設定します。

    System.setProperty("javafx.macosx.embedded", "true"); 
    java.awt.Toolkit.getDefaultToolkit(); 
    
  2. テイクEDTとJavaFXでAWTの処理が行われるように注意してください。JavaFXアプリケーションスレッドで処理されます。

私は最近MacでJavaFX/Swingの問題を扱っていたので、これが私の興味を引いた。下のコードを試してみたら、それはあなたのために働くのですか?(これは、アプリケーションのウィンドウの背景として、スケーリングされたスクリーンショットを置く必要があります。)

import java.awt.AWTException; 
import java.awt.DisplayMode; 
import java.awt.GraphicsDevice; 
import java.awt.GraphicsEnvironment; 
import java.awt.Rectangle; 
import java.awt.Robot; 
import java.awt.image.BufferedImage; 

import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.embed.swing.SwingFXUtils; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.image.Image; 
import javafx.scene.image.ImageView; 
import javafx.scene.layout.Pane; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

import javax.swing.SwingUtilities; 

public class SO extends Application { 

    @Override 
    public void start(Stage stage) throws Exception { 
     final Pane pane = new StackPane(); 
     Scene scene = new Scene(pane, 600, 300); 
     stage.setScene(scene); 
     Button b = new Button("Snap"); 
     final ImageView iv = new ImageView(); 
     iv.fitWidthProperty().bind(pane.widthProperty()); 
     iv.fitHeightProperty().bind(pane.heightProperty()); 
     pane.getChildren().add(iv); 
     pane.getChildren().add(b); 
     b.setOnAction(new EventHandler<ActionEvent>() { 
      @Override 
      public void handle(ActionEvent event) { 
       SwingUtilities.invokeLater(new Runnable() { 
        @Override 
        public void run() { 
         doSnap(iv); 
        } 
       }); 
      } 
     }); 
     stage.show(); 
    } 

    protected void doSnap(final ImageView iv) { 
     GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
     GraphicsDevice[] gs = ge.getScreenDevices(); 

     Robot robot = null; 
     try { 
      robot = new Robot(gs[gs.length-1]); 
     } catch (AWTException e) { 
      e.printStackTrace(); 
      return; 
     } 
     DisplayMode mode = gs[0].getDisplayMode(); 
     Rectangle bounds = new Rectangle(0, 0, mode.getWidth(), mode.getHeight()); 
     final BufferedImage bi = robot.createScreenCapture(bounds); 
     Platform.runLater(new Runnable() { 
      @Override 
      public void run() { 
       Image im = SwingFXUtils.toFXImage(bi, null); 
       iv.setImage(im); 
      } 
     }); 
    } 

    public static void main(String[] args) { 
     System.setProperty("javafx.macosx.embedded", "true"); 
     java.awt.Toolkit.getDefaultToolkit(); 
     Application.launch(args); 
    } 

} 
関連する問題