JavaFX 2.1:ツールキットが初期化されていません



Javafx 2 1 Toolkit Not Initialized



から転送 JavaFX 2.1: T oolkitが初期化されていません

まず、問題

私のアプリケーションはSwingに基づいています。 JavaFXを導入し、セカンダリディスプレイにシーンをレンダリングするように構成したいと思います。 JFrameを使用してJFXPanelを保持できるJFXPanelを保存できますが、JavaFXAPIを使用してこれを実行したいと思います。



com.sun.glass.ui.Applicationをサブクラス化し、Application.launch(this)を使用することは、呼び出し元のスレッドがブロックされるため、オプションではありません。

Swing EDTからステージをインスタンス化すると、次のエラーが発生します。



java.lang.IllegalStateException: Toolkit not initialized

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

解決

サブクラスJavaFXアプリケーションクラス そして、別のスレッドで実行します。次に例を示します。



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

補足:Application.launch()メソッドは1つのClassパラメータを受け入れるため、初期化されたJavaFX環境を表すにはグローバル変数を使用する必要があります。

別の方法: Swingイベントディスパッチャスレッドで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番目のものを選択しました。

(1)回答1

JavaFXを使用する唯一の方法は、アプリケーションをサブクラス化するか、JFXPanelを使用することです。これは、envとツールキットが用意されているからです。

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

Swing / AWTと同じVMでJavaFXを使用している場合は、JFXPanelを使用することをお勧めしますが、詳細については、次を参照してください。 JavaFxでAWTを使用しても大丈夫ですか?

(2)回答2

解決策を見つけました。 JavaFX Platform.runLaterを呼び出す前にSwingEDTから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() { @Override public void handle(WindowEvent windowEvent) { System.exit(0) } }) .build() .show() } }) } }) } }

(3)回答3

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 yourTable = new TableView() .... do your testing stuff } }

この記事はテストとは何の関係もありませんが、単体テストを機能させるのに役立ちます

  • BeforeClass initToolkitがないと、unittestでTableViewをインスタンス化すると、ツールキットメッセージが欠落します。

(4)回答4

次のコマンドを呼び出して、ツールキットを明示的に初期化することもできます。com.sun.javafx.application.PlatformImpl#startup(Runnable)

* implのおかげで少しハッキーですが、使用したくない場合はApplicationまたはJXFPanel何らかの理由で役立ちます。

から この記事 自分を再公開する

(5)回答5

ソースコードを確認しました。これは初期化するためです。

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

そしてそれをやめます

com.sun.javafx.application.PlatformImpl.exit()