因此,当前我正在开发一个项目,该项目需要在一个方法中启动一个快速的Javafx窗口。因为我不想让类扩展Application,所以我的解决方案是创建一个扩展应用程序的内部类,并通过创建内部类的实例并在内部类中调用launch来在方法内启动javafx窗口,如下所示
public void createWindow() {
Fx window = new Fx();
window.launchWindow();
}
public static class Fx extends Application {
private void launchWindow() {
launch();
}
public void start(Stage stage) {
//javafx code
}
}
问题在于内部类必须是公共的,因为javafx要求启动的类是公共的,否则它将引发异常。这导致用户现在可以在内部类公开时访问它。
是否可以将其设为私有或其他解决方法?还是我应该采取另一种方式做到这一点?
答案 0 :(得分:7)
使用Application.launch
并不是启动JavaFX运行时的唯一方法,它只是标准且使用最多的选项。另一种选择是使用Platform.startup(Runnable)
(JavaFX 9+)。该方法将启动JavaFX运行时,并在 JavaFX Application Thread 上调用给定的Runnable
。
Platform.startup(() -> {
Stage stage = new Stage();
stage.setScene(/* your built scene */);
stage.show();
});
此设置需要牢记一些重要事项:
每个JVM实例只能启动一次JavaFX运行时;第二次调用startup
将导致IllegalStateException
。如果您的方法可以被多次调用,那么您需要在第二次及以后的调用中使用Platform.runLater(Runnable)
。
在默认情况下,关闭最后一个Stage
后,JavaFX运行时将退出。一旦发生这种情况,除非重新启动整个JVM,否则无法再次启动它。要阻止这种情况发生,请使用Platform.setImplicitExit(false)
。现在,您将使用Platform.exit()
来停止JavaFX运行时。
使用startup
绕过正常的JavaFX生命周期。换句话说,将不会创建Application
子类的实例,并且不会调用init()
,start(Stage)
和stop()
方法。
如果应用程序的JavaFX部分不重要,请注意,只要应用程序存在,运行时将在启动后消耗资源。即使关闭了最后一个窗口(隐式出口已设置为false
),也是如此。解决此问题的方法(可能很简单)是在另一个进程中启动JavaFX,该进程可以根据需要进行销毁。
如果您使用的是Java 9+,则另一个(或至少是免费的)选择是使用模块。将您的Application
类放在仅导出到javafx.graphics
模块的包中。这将阻止其他模块访问您的Application
类(即使它是公共的)。
module app {
requires javafx.graphics;
exports com.example to javafx.graphics;
}
注意:这不会阻止人们使用类路径或使用--add-exports
,但这将是“错误地使用您的库”,这意味着行为未指定。