问题描述
我的应用程序是基于Swing的.我想介绍JavaFX并将其配置为在辅助显示器上渲染场景.我可以使用JFrame来容纳JFXPanel,而JFXPanel可以容纳JFXPanel,但我想使用JavaFX API来实现.
My application is Swing-based. I would like to introduce JavaFX and configure it to render a Scene on a secondary display.I could use a JFrame to hold a JFXPanel which could hold a JFXPanel but I would like to achieve this with JavaFX API.
不能将com.sun.glass.ui.Application子类化并使用Application.launch(this),因为调用线程将被阻止.
Subclassing com.sun.glass.ui.Application and using Application.launch(this) is not an option because the invoking thread would be blocked.
从Swing EDT实例化Stage时,我得到的错误是:
When instantiating a Stage from Swing EDT, the error I get is:
java.lang.IllegalStateException: Toolkit not initialized
有指针吗?
结论
问题:不平凡的Swing GUI应用程序需要运行JavaFX组件.应用程序的启动过程会在启动相关服务层后初始化GUI.
Problem: Non-trivial Swing GUI application needs to run JavaFX components. Application's startup process initializes the GUI after starting up a dependent service layer.
解决方案
子类JavaFX Application类,并在单独的线程中运行它,例如:
Subclass JavaFX Application class and run it in a separate thread e.g.:
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环境已初始化.
Sidenote: Because Application.launch() method takes a Class<? extends Application>
as an argument, one has to use a global variable to signal JavaFX environment has been initialized.
替代方法:在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环境为止.
By using this approach the calling thread will wait until JavaFX environment is set up.
选择您认为合适的任何解决方案.我选择了第二个,因为它不需要全局变量来表示JavaFX环境的初始化,而且也不会浪费线程.
Pick any solution you see fit. I went with the second one because it doesn't need a global variable to signal the initialization of JavaFX environment and also doesn't waste a thread.
推荐答案
找到了解决方案.如果我只是在调用JavaFX Platform.runLater之前从Swing EDT创建一个JFXPanel,它将起作用.我不知道此解决方案的可靠性如何,如果结果不稳定,我可能会选择JFXPanel和JFrame.
Found a solution. If I just create a JFXPanel from Swing EDT before invoking JavaFX Platform.runLater it works.I don't know how reliable this solution is, I might choose JFXPanel and JFrame if turns out to be unstable.
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();
}
});
}
});
}
}
这篇关于JavaFX 2.1:工具包未初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!