考虑一个非fx的现有应用程序,将其称为Business
。
Business
公开一个Model
对象,该对象又公开了一些属性。Model
也接受这些属性的侦听器。
我的问题是关于 将 JavaFx gui 添加
到此类应用程序。将GuiApp
明显延长javafx.application.Application
,将需要一个参考Model
对象。
在寻找将非String参数传递给GuiApp
我的解决方案时,我发现了几种不同的方法:
静态方法:例如,已Business
初始化对Model
in 的静态引用GuiApp
。在这里可以看到使用静电的一个示例。
JavaFx 9方法:如此处所示 ,您无需扩展即可启动JavaFx应用程序Application
。
更改工作流程方法:将现有工作流程更改为具有GuiApp
initialize 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
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 Platform#startup
当您 不能 将该Application#start
方法用作应用程序的入口点时,这是我发现的最佳解决方案。
如fabians 答案所示,从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;
}
}
问题内容: 我是android新手,非常习惯于网络开发。在javascript中,当您要执行异步任务时,可以将函数作为参数传递(回调): 我想知道我们是否可以对android进行相同的操作,将函数引用传递给方法,然后它将运行它。 有什么建议 ? 问题答案: 是的,回调的概念在Java中也非常存在。在Java中,您可以这样定义一个回调: 人们通常会在这样的内部嵌套这些侦听器定义: 回调的完整实现如下
考虑这个简单的程序: 当我写的时候,我希望得到: 13 42 13 42 13 42 但是我得到的是: 13 42 0 42 0 42 当然,问题在于通过引用来吸收最后2个参数。因此,如果它们中的任何一个碰巧在正在操作的范围内,则结果可能是意外的。我可以通过添加一个临时变量来解决这个问题: 我知道C 11为我们提供了各种类型的工具,我是否可以简单地将这个值强制为非引用类型并内联传递,而不创建临时类
问题内容: 我有一个使用while循环创建的按钮。所以while循环为mysql表中的每一行创建一个表行。 我为该按钮编写了一行代码,该代码针对表的每一行再次创建,并且每个按钮基于该记录具有不同的值。 问题是我想使用它并以模式查看它,以便可以使用mysqli查询检索具有相同ID的记录。 这是模态的代码。 问题答案: 如果可以,我对你是正确的。 模态触发按钮 Bootstrap Modal事件以使用
问题内容: 我试图将SharedPreferences首选项作为AsyncTask中doInBackground函数的参数传递。我已经给它传递了一个字符串(URL),所以我也需要将首选项也作为字符串传递。我可以简单地使用prefs.toString()将其转换为字符串吗? 这是我设置偏好的地方: 问题答案: 你不能,你不应该。您可以轻松地读取内部首选项,而无需将任何内容传递给方法,只需使用即可:
问题内容: 我正在尝试执行一个Web服务,该服务返回带有以下代码的DataTable: 如果Web服务返回一个类,则它将起作用,因此它与输入参数等无关。仅当Web方法返回一个数据表(该数据表仅包含2列和2行用于我正在执行的测试)时,它才会失败。 WebService类装饰有[ScriptService]属性,因此我认为ASP.NET将自动将返回值序列化为JSON。它似乎不适用于数据表。 我发现的唯
问题内容: 我正在使用Go内置的http服务器,并拍拍来响应一些URL: 我需要向该处理函数传递一个额外的参数-一个接口。 如何向处理程序函数发送额外的参数? 问题答案: 通过使用闭包,您应该能够做您想做的事情。 更改为以下内容(未测试): 然后对