【问题标题】:Passing reference to javafx.application.Application传递对 javafx.application.Application 的引用
【发布时间】:2019-03-30 22:05:12
【问题描述】:

考虑一个非 fx 现有应用程序,我们称之为Business

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

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

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

  • 静态方法:例如让BusinessGuiApp 中初始化对Model 的静态引用。 here 是使用静态的一个例子。

  • JavaFx 9 方法:如 here 所示,您可以在不扩展 Application 的情况下启动 JavaFx 应用程序。

  • 更改工作流方法:更改现有工作流以使 GuiApp 初始化 BusinessApphere 是此类工作流程的一个示例。

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

【问题讨论】:

  • 嗯...我之前的评论在哪里?也许没有发送,还没有足够的咖啡;)所以我们又来了:为什么你有 2 个类型的应用程序(或者什么是业务应用程序?)无论如何,听起来耦合太多:让模型独立运行并传递它。
  • @kleopatra 很抱歉,如果我没有澄清清楚:只有 gui 类扩展 Application。 Gui 类需要Model 的引用,BusinessApp 也是如此。我会改名BusinessApp,可能会误导。
  • 好的,Business 在哪里/如何生活?
  • @kleopatra 我试图了解可能性的合理范围。为了这个小型研究,我们可以假设 BusinessGuiApp 共享同一台 Windows 机器。
  • @isnot2bad 感谢您的评论。关于:“在回答你的类似问题”发布的链接不会发布到我的问题。

标签: java javafx javafx-9


【解决方案1】:

我将尝试演示一些在 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 answer
如果您想将现有的 java 应用程序与 java-fx 绑定并使用 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 平台#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;
    }
}

【讨论】:

    猜你喜欢
    • 2016-12-05
    • 2016-06-06
    • 2013-06-16
    • 2016-03-24
    • 1970-01-01
    • 1970-01-01
    • 2016-09-14
    • 1970-01-01
    • 2015-10-31
    相关资源
    最近更新 更多