Передача ссылки на javafx.application.Application - PullRequest
0 голосов
/ 26 октября 2018

Рассмотрим не-fx существующее приложение, назовем его Business.

Business предоставляет объект Model, который, в свою очередь, предоставляет некоторые свойства.Model также принимает слушателей этих свойств.

Мой вопрос о добавлении графического интерфейса JavaFx в такое приложение.GuiApp явно расширяет javafx.application.Application и будет нуждаться в ссылке на объект Model.

Поиск решения для передачи нестрокового параметра в GuiApp Я нашел несколько разных подходов:

  • Статический подход: например, пусть Business инициализирует статическую ссылку на Model в GuiApp.Один пример использования статики можно увидеть здесь .

  • Подход JavaFx 9: как показано здесь вы можете запускать приложение JavaFx без расширения Application.

  • Изменить подход рабочего процесса: изменить существующий рабочий процесс, чтобы GuiApp инициализировать BusinessApp.Один пример такого рабочего процесса можно увидеть здесь .

Существуют ли другие жизнеспособные подходы?Лучшая практика?

1 Ответ

0 голосов
/ 30 октября 2018

Я попытаюсь продемонстрировать несколько разных подходов для передачи ссылки между 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-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.Все, что вам нужно сделать, это изменить 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:

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