ScalaFX(或 JavaFX)- 多次从另一个主要 class 调用 GUI
ScalaFX (or JavaFX) - Calling GUI from another main class multiple times
我在继续上一个问题:
- 我正在为模拟包编写一个独立的可视化包
- 模拟包是由我们团队中的一个人用 Scala 编写的
我想做的是为这个模拟包创建一个类似 matplotlib 的包。我设想的最终用途看起来像 matplotlib:
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.show()
plt.plot([10, 20, 3000, 4121212])
plt.ylabel('some numbers')
plt.show()
对于我的包裹,我会做类似的事情。这里假设 myFXPackage 是一个用 ScalaFX 编写的图表包。在我的驱动程序中 class:
Import myFXPackage
// run some simulation code here...
myFXPackage.plot(results)
// run some MORE simulation code here...
myFXPackage.plot(results)
现在看来,对于ScalaFX,整个应用只能有一个入口点;这是 JFXApp class。但是,我想在我的 DRIVER class 中多次导入包并简单地 运行 这段代码,如上所示。所以不知何故 DRIVER class 将如何调用 ScalaFX 和 运行 情节,关闭它,然后 运行 另一个情节。
这可行吗?如果是这样,我该怎么做呢?
大多数 JavaFX 示例代码将 main
方法与 Application
subclass 方法混为一谈,在许多情况下甚至会在相同 class。不一定有这样做的理由,在后一种情况下,这不是一个特别好的设计。
假设您在 UI 代码中适当地分离关注点,您可能有一个 class 像
public class MainUI {
private BorderPane root ;
public MainUI() {
root = new BorderPane();
// do layout, register event handlers, etc etc
}
public Pane getView() {
return root ;
}
}
然后如果你想要一个独立的 JavaFX 应用程序,你会做
public class JavaFxApp extends Application {
@Override
public void start(Stage stage) {
MainUI ui = new MainUI();
Scene scene = new Scene(ui.getView());
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
但这不是您可以使用 UI class 的唯一地方。在 JavaFX 中(与大多数 UI 工具包一样),您 必须 创建一个新阶段,并在 UI 线程上执行其他 UI 任务(即 FX 应用程序线程)。
此外,在 JavaFX 中,您必须显式启动 FX 工具包。在上面的代码中,这是通过 Application.launch()
方法完成的。
JavaFX 9 引入了一个 Platform.startup(Runnable)
,它启动 FX 工具包并在 FX 应用程序线程上执行提供的 Runnable
。
因此,使用 JavaFX 9 及更高版本,您可以拥有类似
的代码
public class SomeApp {
public static void main(String[] args) {
// start FX toolkit
// Since we don't want it to exit when we close a window, set
// implicit exit to false:
Platform.startup(() -> Platform.setImplicitExit(false));
// do some other stuff...
// whenever you need to:
Platform.runLater(SomeApp::showStage);
// do other stuff...
}
private static void showStage() {
Scene scene = new Scene(new MainUI().getView());
Stage stage = new Stage();
stage.show();
}
}
在 JavaFX 9 之前,您仍然可以这样做,但是您需要启动一个 "blank" 应用程序:
public class FXStartup extends Application {
@Override
public void start(Stage ignored) {
// probably need this:
Platform.setImplicitExit(false);
}
}
请注意,launch()
方法会阻塞,直到工具包退出,因此您的应用程序需要在另一个线程中启动它:
public class SomeApp {
public static void main(String[] args) {
// start FX toolkit
new Thread(() -> Application.launch(FXStartup.class, args)).start();
// do some other stuff...
// whenever you need to:
Platform.runLater(SomeApp::showStage);
// do other stuff...
}
private static void showStage() {
Scene scene = new Scene(new MainUI().getView());
Stage stage = new Stage();
stage.show();
}
}
我在继续上一个问题:
- 我正在为模拟包编写一个独立的可视化包
- 模拟包是由我们团队中的一个人用 Scala 编写的
我想做的是为这个模拟包创建一个类似 matplotlib 的包。我设想的最终用途看起来像 matplotlib:
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.show()
plt.plot([10, 20, 3000, 4121212])
plt.ylabel('some numbers')
plt.show()
对于我的包裹,我会做类似的事情。这里假设 myFXPackage 是一个用 ScalaFX 编写的图表包。在我的驱动程序中 class:
Import myFXPackage
// run some simulation code here...
myFXPackage.plot(results)
// run some MORE simulation code here...
myFXPackage.plot(results)
现在看来,对于ScalaFX,整个应用只能有一个入口点;这是 JFXApp class。但是,我想在我的 DRIVER class 中多次导入包并简单地 运行 这段代码,如上所示。所以不知何故 DRIVER class 将如何调用 ScalaFX 和 运行 情节,关闭它,然后 运行 另一个情节。
这可行吗?如果是这样,我该怎么做呢?
大多数 JavaFX 示例代码将 main
方法与 Application
subclass 方法混为一谈,在许多情况下甚至会在相同 class。不一定有这样做的理由,在后一种情况下,这不是一个特别好的设计。
假设您在 UI 代码中适当地分离关注点,您可能有一个 class 像
public class MainUI {
private BorderPane root ;
public MainUI() {
root = new BorderPane();
// do layout, register event handlers, etc etc
}
public Pane getView() {
return root ;
}
}
然后如果你想要一个独立的 JavaFX 应用程序,你会做
public class JavaFxApp extends Application {
@Override
public void start(Stage stage) {
MainUI ui = new MainUI();
Scene scene = new Scene(ui.getView());
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
但这不是您可以使用 UI class 的唯一地方。在 JavaFX 中(与大多数 UI 工具包一样),您 必须 创建一个新阶段,并在 UI 线程上执行其他 UI 任务(即 FX 应用程序线程)。
此外,在 JavaFX 中,您必须显式启动 FX 工具包。在上面的代码中,这是通过 Application.launch()
方法完成的。
JavaFX 9 引入了一个 Platform.startup(Runnable)
,它启动 FX 工具包并在 FX 应用程序线程上执行提供的 Runnable
。
因此,使用 JavaFX 9 及更高版本,您可以拥有类似
的代码public class SomeApp {
public static void main(String[] args) {
// start FX toolkit
// Since we don't want it to exit when we close a window, set
// implicit exit to false:
Platform.startup(() -> Platform.setImplicitExit(false));
// do some other stuff...
// whenever you need to:
Platform.runLater(SomeApp::showStage);
// do other stuff...
}
private static void showStage() {
Scene scene = new Scene(new MainUI().getView());
Stage stage = new Stage();
stage.show();
}
}
在 JavaFX 9 之前,您仍然可以这样做,但是您需要启动一个 "blank" 应用程序:
public class FXStartup extends Application {
@Override
public void start(Stage ignored) {
// probably need this:
Platform.setImplicitExit(false);
}
}
请注意,launch()
方法会阻塞,直到工具包退出,因此您的应用程序需要在另一个线程中启动它:
public class SomeApp {
public static void main(String[] args) {
// start FX toolkit
new Thread(() -> Application.launch(FXStartup.class, args)).start();
// do some other stuff...
// whenever you need to:
Platform.runLater(SomeApp::showStage);
// do other stuff...
}
private static void showStage() {
Scene scene = new Scene(new MainUI().getView());
Stage stage = new Stage();
stage.show();
}
}