java - 传递对 javafx.application.Application 的引用
问题描述
考虑一个非 fx 现有应用程序,我们称之为Business
.
Business
公开一个Model
对象,该对象又公开一些属性。Model
还接受这些属性的侦听器。
我的问题是关于将 JavaFx gui 添加到此类应用程序中。GuiApp
显然扩展javafx.application.Application
并且需要对对象的引用Model
。
寻找将非字符串参数传递给我的解决方案,GuiApp
我发现了几种不同的方法:
静态方法:例如初始化一个对in
Business
的静态引用。这里可以看到一个使用静力学的例子。Model
GuiApp
JavaFx 9 方法:如此处所示 ,您可以启动 JavaFx 应用程序而无需扩展
Application
.更改工作流方法:将现有工作流更改为具有
GuiApp
初始化BusinessApp
。可以在此处查看此类工作流程的一个示例。
还有其他可行的方法吗?最佳实践 ?
解决方案
我将尝试演示一些在 java 程序和 java-fx 程序之间传递引用的不同方法。
我发布它是希望它能帮助一些有类似需求的未来读者。我也希望它可以通过其他解决方案鼓励其他答案。
发布的代码不应被视为正确的实现,而是旨在阐明不同方法的简短代码。为此,我将介绍一个简单的监听界面:
interface Observe{ void update(int i); }
一个 java 类,代表一个现有的业务应用程序:
public class JavaApp {
private Observe observer; private int counter = 0;
JavaApp(Observe observer){ //not null safe
this.observer = observer;
}
void process() {
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
observer.update(counter >=100 ? 0 : ++counter);
}
}, 1000,1000);
}
}
应添加到现有业务应用程序中的 java-fx 应用程序,监听它并用作视图:
public class JavaFxApp extends Application implements Observe{
private Label label;
@Override public void start(Stage stage) {
label = new Label("waiting");
BorderPane pane = new BorderPane(label);
Scene scene = new Scene(pane, 100, 100);
stage.setScene(scene);
stage.show();
}
@Override public void update(int i) {
Platform.runLater(()-> label.setText(String.valueOf(i)));
}
}
我们如何Observe
在两个应用程序之间共享引用,在这种情况下是对实例的引用?
方法 1:将start()
方法视为应用程序的入口点(请参阅 James_D答案)
如果您想将现有的 java 应用程序与 java-fx 绑定并使用 java-fxApplication
作为入口点,这很简单:
public class JavaFxApp extends Application implements Observe{
private Label label;
@Override public void start(Stage stage) {
JavaApp main = new JavaApp(this);
label = new Label("waiting");
BorderPane pane = new BorderPane(label);
Scene scene = new Scene(pane, 100, 100);
stage.setScene(scene);
stage.show();
new Thread(()-> { main.process();}).start(); //launch the business process
}
@Override public void update(int i) {
Platform.runLater(()-> label.setText(String.valueOf(i)));
}
public static void main(String[] args) { launch(); }
}
方法 2:使用 JavaFX 9 Platform#startup
这是我找到的最佳解决方案,当您不能使用该Application#start
方法作为应用程序的入口点时。
正如 fabians answer中所展示的,作为 off java-fx 9,您可以在不扩展的情况下启动Application
. 您所要做的就是修改main
java 应用程序的:
public class JavaApp {
private Observe observer; private int counter = 0;
JavaApp(Observe observer){//not null safe
this.observer = observer;
}
void process() {
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override public void run() {
observer.update(counter >=100 ? 0 : ++counter);
}
}, 1000,1000);
}
public static void main(String[] args) {
JavaFxApp view = new JavaFxApp(); //initialize JavaFx application
JavaApp main = new JavaApp(view);
Platform.startup(() -> {//launch JavaFx application
Stage stage = new Stage();
try {
view.start(stage);
} catch (Exception ex) {ex.printStackTrace();}
});
main.process(); //run business process
}
}
方法 3:使用静态成员
例如在 java-fx 应用程序中引入静态 getter:
public class JavaFxApp extends Application {
private static Label label = new Label("waiting");
@Override public void start(Stage stage) {
BorderPane pane = new BorderPane(label);
Scene scene = new Scene(pane, 100, 100);
stage.setScene(scene);
stage.show();
}
static Observe getObserver() {
return JavaFxApp::update;
}
private static void update(int i) {
Platform.runLater(()-> label.setText(String.valueOf(i)));
}
}
并在java应用程序中使用它:
public class JavaApp {
private Observe observer; private int counter = 0;
JavaApp(Observe observer){//not null safe
this.observer = observer;
}
void process() {
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
observer.update(counter >=100 ? 0 : ++counter);
}
}, 1000,1000);
}
public static void main(String[] args){
new Thread(()-> Application.launch(JavaFxApp.class)).start();
Observe observer = JavaFxApp.getObserver(); //get static observer reference
JavaApp main = new JavaApp(observer);
main.process();
}
}
获得静态引用的更好方法可能是(基于此答案):
public class JavaFxApp extends Application implements Observe{
private static final CountDownLatch latch = new CountDownLatch(1);
private static Observe observer = null;
private Label label;
@Override public void init() {
observer = this;
latch.countDown();
}
@Override public void start(Stage stage){
label = new Label("waiting");
BorderPane pane = new BorderPane(label);
Scene scene = new Scene(pane, 100, 100);
stage.setScene(scene);
stage.show();
}
@Override public void update(int i) {
Platform.runLater(()-> label.setText(String.valueOf(i)));
}
static Observe getObserver() {
try {
latch.await();
} catch (InterruptedException e) { e.printStackTrace(); }
return observer;
}
}
推荐阅读
- c# - 从编译的代码中恢复 Umbraco 的自定义代码
- python - 如何在 python 3.6 上制作一个简单的网络浏览器?
- javascript - 如何让 React setupProxy 与 express.js 一起正常工作
- javascript - 角删除所有完成不刷新不工作
- html - CSS过滤器禁用固定位置
- rest - 调用 AWS Lambda 端点
- xcode - SCNMatrix4 vs simd - 列专业还是行专业?
- php - 我应该在控制器的构造函数中注入存储库类或模型类吗?
- ios - 取消 iOS 上的所有展会本地预定通知
- python - 基于霍夫线创建 TensorFlow 模型