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