programing

JavaFX 2.1 : 툴킷이 초기화되지 않았습니다.

copyandpastes 2021. 1. 15. 20:16
반응형

JavaFX 2.1 : 툴킷이 초기화되지 않았습니다.


내 응용 프로그램은 스윙 기반입니다. JavaFX를 소개하고 보조 디스플레이에서 장면을 렌더링하도록 구성하고 싶습니다. JFrame을 사용하여 JFXPanel을 보유 할 수있는 JFXPanel을 보유 할 수 있지만 JavaFX API로이를 달성하고 싶습니다.

com.sun.glass.ui.Application을 서브 클래 싱하고 Application.launch (this)를 사용하는 것은 호출 스레드가 차단되기 때문에 옵션이 아닙니다.

Swing EDT에서 Stage를 인스턴스화 할 때 발생하는 오류는 다음과 같습니다.

java.lang.IllegalStateException: Toolkit not initialized

포인터가 있습니까?


편집 : 결론

문제 : 사소하지 않은 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>인수로 사용하므로 JavaFX 환경이 초기화되었음을 알리기 위해 전역 변수를 사용해야합니다.

다른 방법 : Swing Event Dispatcher Thread에서 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 환경의 초기화를 알리기 위해 전역 변수가 필요하지 않고 스레드를 낭비하지 않기 때문에 두 번째 방법을 사용했습니다.


JavaFX로 작업하는 유일한 방법은 Application을 하위 클래스로 분류하거나 JFXPanel을 사용하는 것입니다. 정확히 env와 툴킷을 준비하기 때문입니다.

블로킹 스레드는을 사용하여 해결할 수 있습니다 new Thread(...).

Swing / AWT와 동일한 VM에서 JavaFX를 사용하는 경우 JFXPanel을 사용하는 것이 좋지만 여기에서 자세한 내용을 확인할 수 있습니다. JavaFx에서 AWT를 사용해도 괜찮습니까?


해결책을 찾았습니다. JavaFX Platform.runLater를 호출하기 전에 Swing 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();
                    }
                });
            }
        });
    }
}

나는 소스 코드를 확인했고 이것은 그것을 초기화하는 것입니다.

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

종료하려면

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

javaFX tableview 업데이트를 테스트하기 위해 unittest를 만들 때 다음을 사용했습니다.

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를 인스턴스화하면 툴킷이 누락되었다는 메시지가 표시됩니다.

다음을 호출하여 툴킷을 명시 적으로 초기화하는 방법도 있습니다. com.sun.javafx.application.PlatformImpl#startup(Runnable)

Little bit hacky, due to using *Impl, but is useful, if you don't want to use Application or JXFPanel for some reason.

re-posting myself from this post


Since JavaFX 9, you can run JavaFX application without extending Application class, by calling Platform.startup():

Platform.startup(() ->
{
    // This block will be executed on JavaFX Thread
});

This method starts the JavaFX runtime.


private static Thread thread;

public static void main(String[] args) {

    Main main = new Main();
    startup(main);
    thread = new Thread(main);
    thread.start();
}

public static void startup(Runnable r) {
    com.sun.javafx.application.PlatformImpl.startup(r);
}

@Override
public void run() {
    SoundPlayer.play("BelievexBelieve.mp3");
}

This is my solution. The class is named Main and implements Runnable. Method startup(Runnable r) is the key.

ReferenceURL : https://stackoverflow.com/questions/11273773/javafx-2-1-toolkit-not-initialized

반응형