2012-06-30 4 views
44

私のアプリケーションは、Swingベースです。私はJavaFXのを導入し、セカンダリディスプレイ上のシーンをレンダリングするように設定したいと思います。 私はJFXPanelを握ることができるが、私はJavaFXのAPIでこれを実現したいと思いJFXPanelを保持するためのJFrameを使用することができます。呼び出し元のスレッドがブロックされるのでのJavaFX 2.1:ツールキット初期化されていません

サブクラスcom.sun.glass.ui.ApplicationとApplication.launchを使用して(これは)オプションではありません。

スイングEDTからステージをインスタンス化する場合、私が得るエラーは次のとおりです。

java.lang.IllegalStateException: Toolkit not initialized 

任意のポインタ?


EDIT:結論

問題:非自明のSwing GUIアプリケーションは、JavaFXのコンポーネントを実行する必要があります。アプリケーションの起動プロセスは、依存サービスレイヤを起動した後にGUIを初期化します。

ソリューション

サブクラスのJavaFX Applicationクラスと別のスレッドなどでそれを実行します。

public class JavaFXInitializer extends Application { 
    @Override 
    public void start(Stage stage) throws Exception { 
     // JavaFX should be initialized 
     someGlobalVar.setInitialized(true); 
    } 
} 

追記:Application.launch()メソッドは、引数としてClass<? extends Application>がかかるので、1 JavaFX環境が初期化されたことを通知するためにグローバル変数を使用する必要があります。

代替アプローチ:スイングイベントディスパッチャスレッドにJFXPanelをインスタンス化:

final CountDownLatch latch = new CountDownLatch(1); 
SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     new JFXPanel(); // initializes JavaFX environment 
     latch.countDown(); 
    } 
}); 
latch.await(); 

このアプローチに呼び出し元のスレッドを使用することによりJavaFXの環境が設定されるまで待機します。

あなたが合っている解決策を選んでください。私はJavaFX環境の初期化を通知するためのグローバル変数は必要なく、スレッドを無駄にしないため、2番目の変数に行きました。

+0

NB、それを終了するには、次のとおりです。仕事に推奨される解決策をSwingアプリケーションのJavaFXを使用すると、JFXPanelを作成し、JavaFXシーンをjfxPanel.setScene()メソッドに渡すことができます。 http://docs.oracle.com/javafx/2/api/javafx/embed/swing/JFXPanel.htmlを参照してください。 –

+0

@SergeyGrinev:まあ、コンポーネントによってはJFXPanelで使用されている問題があるため、JavaFX 2を使用する別の方法スイングから高く評価されています。 – dajood

+0

こんにちは。どのコンポーネントに問題がありますか? –

答えて

16

は解決策を見つけました。私はJavaFXのPlatform.runLaterを呼び出す前にスイングEDTからJFXPanelを作成する場合、それは動作します。 このソリューションの信頼性がわかりませんが、JFXPanelとJFrameを選択すると不安定になることがあります。

public class BootJavaFX { 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new JFXPanel(); // this will prepare JavaFX toolkit and environment 
       Platform.runLater(new Runnable() { 
        @Override 
        public void run() { 
         StageBuilder.create() 
           .scene(SceneBuilder.create() 
             .width(320) 
             .height(240) 
             .root(LabelBuilder.create() 
               .font(Font.font("Arial", 54)) 
               .text("JavaFX") 
               .build()) 
             .build()) 
           .onCloseRequest(new EventHandler<WindowEvent>() { 
            @Override 
            public void handle(WindowEvent windowEvent) { 
             System.exit(0); 
            } 
           }) 
           .build() 
           .show(); 
        } 
       }); 
      } 
     }); 
    } 
} 
+0

JFXPanelを既にお持ちの場合、なぜFXコードを入れたくないのですか? –

+0

このソリューションでは、JavaFX環境を実行するための回避策としてJFXPanelのみを使用しています。私はJavaFXでPlatform.initialize()のようなものが好きだったでしょう。 –

+5

あなたはそれを動作させるためにすべてを行う必要がありますか?ばかげています。 –

19

JavaFXを使用する唯一の方法は、envとツールキットを用意しているため、Applicationをサブクラス化するか、JFXPanelを使用することです。

ブロッキングスレッドはnew Thread(...)を使用して解決できます。

私はあなたがスイング/ AWTと同じVMでのJavaFXを使用している場合はJFXPanelを使用することをお勧めしますが、ここで詳細を見つけることができます:Is it OK to use AWT with JavaFx?

+0

私のアプリケーションはSwingベースなので、私は新しいスレッド(...)を避けていました。ヒントをありがとう。 –

+0

どのように接続されていますか?任意のJavaコードでスレッドを使用できます。 –

+0

私のアプリケーションには、特定の起動ルーチンがあります。 GUIの初期化は、メインスレッドから呼び出された後の段階で行われます。 JavaFX環境を開始し、完了したら通知を受け取ることを検討していました。 Application.launchを使用すると、呼び出しスレッドをブロックするため、私にとっては解決策ではありません。 –

4

私は

  • を動作するように私のユニットテストを取得するために私を助け、このポストは関連テストされていなくても、試験のJavaFXテーブルビューの更新を

    public class testingTableView { 
         @BeforeClass 
         public static void initToolkit() throws InterruptedException 
         { 
          final CountDownLatch latch = new CountDownLatch(1); 
          SwingUtilities.invokeLater(() -> { 
           new JFXPanel(); // initializes JavaFX environment 
           latch.countDown(); 
          }); 
    
          if (!latch.await(5L, TimeUnit.SECONDS)) 
           throw new ExceptionInInitializerError(); 
         } 
    
         @Test 
         public void updateTableView() throws Exception { 
    
          TableView<yourclassDefiningEntries> yourTable = new TableView<>(); 
          .... do your testing stuff 
    
         } 
        } 
    

    をユニットテストを作成する際に、以下の使用BeforeClassのinitToolkitを使用しない場合、UnitTestのTableViewのインスタンス化でツールキットが見つからないというメッセージが返されます

+0

ありがとうございました...私はJavaFXとテストを理解しようとしています。しかし、ほとんどのJavaFX操作では、「IllegalStateException:この操作はイベント・スレッドのみで許可されています;」が生成されます。そして 'Plaform.runLater()' 'Runnable'の内部での動作はうまくいきません:Swingでは常に' EventQueue 'を使う必要がありました。invokeAndWait() ' - それ以外の場合は、Runnableが実行される前にテストが終了します。 TestFXのようなsthgをJavaFXのテストに使う必要があるのではないでしょうか? –

+0

PSもちろん、ラッチを使ってこの「Runnableが終了するのを待つ」ことができますが、それほどエレガントではありません。 –

+0

@mikerodent私は、ユーティリティが存在するのを待つためにラッチを使用するのはエレガントではないと同意しますが、外部エンティティに依存している場合は、おそらくこれは不器用ではないでしょう – serup

4

あり呼び出すことにより、明示的にツールキットを初期化する方法もあります: com.sun.javafx.application.PlatformImpl#startup(Runnable)

* Implをを使用してのためにリトルビットハックは、しかし、あなたには、いくつかの理由でApplicationまたはJXFPanelを使用したくない場合は、便利です。

this post

+1

私はこれを起立した賛美に答える!私は2つのUIを持っているという目的でアプリケーションを書いています。最初のものはFXで、2番目のものはグラフィックではありません。私のモデルはFXコレクションを使用しています。これがなければ、コレクションを使用することはできず、グラフィックス要素はありません。 – Bday

+0

これは、グラフィックスの前にモデルを開始するときの競合状態も解決します。だから終わりのおかげで! – Bday

+0

驚いたことに、これは実際には動作します – piegames

3

から自分自身を再投稿私は、ソースコードをチェックし、これはそれを

com.sun.javafx.application.PlatformImpl.startup(()->{}); 

を初期化すると

com.sun.javafx.application.PlatformImpl.exit(); 
関連する問題