gpt4 book ai didi

java - 传递对 javafx.application.Application 的引用

转载 作者:行者123 更新时间:2023-11-30 05:56:57 30 4
gpt4 key购买 nike

考虑一个非外汇现有应用程序,我们将其称为Business

Business 公开一个 Model 对象,该对象又公开一些属性。 Model 还接受这些属性的监听器。

我的问题是关于向此类应用程序添加 JavaFx gui。 GuiApp 显然扩展了 javafx.application.Application 并且需要对 Model 对象的引用。

在寻找将非字符串参数传递给 GuiApp 的解决方案时,我发现了几种不同的方法:

  • 静态方法:例如,让 Business 初始化对 GuiApp 中的 Model 的静态引用。可以看到一个使用静态的例子 here

  • JavaFx 9 方法:如所示 here您可以启动 JavaFx 应用程序而无需扩展 Application

  • 更改工作流程方法:更改现有工作流程,让 GuiApp 初始化 BusinessApp 。这种工作流程的一个示例可以参见 here .

还有其他可行的方法吗?最佳实践 ?

最佳答案

我将尝试演示一些在 java 程序和 java-fx 程序之间传递引用的不同方法。
我发布它是希望它能帮助一些 future 有类似需求的读者。我也希望它可以鼓励其他答案和其他解决方案。
发布的代码不应被视为正确的实现,而应被视为旨在阐明不同方法的简短代码。为此,我将引入一个简单的监听接口(interface):

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应用程序,应该添加到现有的业务应用程序中,监听它并用作 View :

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 answer )
如果您想将现有的 java 应用程序与 java-fx 绑定(bind)并使用 java-fx Application 作为入口点,这非常简单直接:

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 中所证明的那样,从 java-fx 9 开始,您无需扩展 Application 即可启动。您所要做的就是修改 java 应用程序的 main :

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();
}
}

获取静态引用的更好方法可能是(基于 this 答案):

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;
}
}

关于java - 传递对 javafx.application.Application 的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53003746/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com