JavaFX控制器,实现非图形事件和后台状态机

JavaFX控制器,实现非图形事件和后台状态机,java,javafx,Java,Javafx,我不久前开始学习JavaFX,我正在尝试从Swing切换到JavaFX。我遇到了一些逻辑实现问题,我想不出一个使用JavaFX的解决方案,我可以使用Swing轻松解决这个问题 我开发的应用程序非常庞大,包含多个已经开发的软件模块,这些模块在某一点上与图形交互。例如,在应用程序中,我有一个智能卡读卡器,当在该读卡器上读卡并且操作员正在使用智能卡进行身份验证时,它在图形上显示已读到有效卡,显示绿卡图标,并允许操作员输入密码。有多个驱动程序,如智能卡读卡器,所有驱动程序都会根据其状态生成事件,它们是否

我不久前开始学习JavaFX,我正在尝试从Swing切换到JavaFX。我遇到了一些逻辑实现问题,我想不出一个使用JavaFX的解决方案,我可以使用Swing轻松解决这个问题

我开发的应用程序非常庞大,包含多个已经开发的软件模块,这些模块在某一点上与图形交互。例如,在应用程序中,我有一个智能卡读卡器,当在该读卡器上读卡并且操作员正在使用智能卡进行身份验证时,它在图形上显示已读到有效卡,显示绿卡图标,并允许操作员输入密码。有多个驱动程序,如智能卡读卡器,所有驱动程序都会根据其状态生成事件,它们是否工作。在当前的解决方案中,所有模块都与中央主软件通信,该软件可以调用Swing图形的功能

应用程序从初始化一个页面开始,当所有设备都工作并且没有错误时,我显示应用程序的第一个页面。如果其中任何一个有错误,我将显示错误页面。我设计了一些fxml,并将它们与自己的控制器连接起来。在初始化页面的控制器中,该方法应如下所示:

@Override
public void initialize(URL url, ResourceBundle rb) {
    if(no_error){
        go to first page
    }else{
        go to out of order page
    }
}
我想实现的第一件事是等待,因为一些驱动程序和设备不会立即工作,例如,等待10个周期,每个周期超时1秒

@Override
public void initialize(URL url, ResourceBundle rb) {
    while (true) {
        if (no_error) {
            go to first page
        } else {
            if (timeout_expired) {
                go to out of order page
            } else {
                wait
                increase timeout
            }
        }
    }
}
我知道initialize方法的目的不是为了这个,上面的代码也不是一个解决方案,我正在从
AsyncTask
中寻找类似
doInBackground
的函数

此外,在控制器的这个应用程序中,我希望实现与图形无关的事件,如智能卡的读取。当智能卡的驱动程序读取卡数据并将数据发送到控制器中实现的功能时,如何连接来自智能卡驱动程序的事件,如下图所示

public void controller_smart_card_read(SmartCard smart_card){
    //Check if valid card from DB
    //Display result
}
另外,在某些场景中,我希望实现一个非活动事件。如果在较长时间内(图形和设备)没有事件,请返回第一页


总而言之,有没有一种方法可以从独立的软件模块访问和触发控制器,有没有一种方法可以在场景和控制器启动并运行时实现
doInBackground()
功能?

创建一个后台线程来执行此功能,并使用Platform.runLater更新UI

比如说

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;

ScheduledExecutorService scheduledExecutorService;
ScheduledFuture<?>       scheduledCheck;

public void start(Stage base) {

  base.setOnCloseRequest(
  scheduledExecutorService.shutdownNow();

  );

  scheduledExecutorService = Executors.newScheduledThreadPool(1);

  Runnable doBackground = () -> {
    //Do background tasks i.e. check card reader
    if(devices_ready && successful_card_read)
      Platform.runLater(() -> {
        //Update Javafx UI
      });
  }
  //scheduleAtFixedRate(Runnable function, wait time before starting runnable, cycle time, timeunit) 
  //the below thread will wait 10 seconds, then execute the doBackground every 1 second
  scheduledCheck = scheduledExecutorService.scheduleAtFixedRate(doBackground,10,1, TimeUnit.SECONDS);
}
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.ScheduledExecutorService;
导入java.util.concurrent.ScheduledFuture;
ScheduledExecutorService ScheduledExecutorService;
ScheduledFuture scheduledCheck;
公共空间启动(后台){
base.setOnCloseRequest(
scheduledExecutorService.shutdownNow();
);
scheduledExecutorService=Executors.newScheduledThreadPool(1);
可运行的doBackground=()->{
//执行后台任务,即检查读卡器
if(设备准备就绪并成功读取卡)
Platform.runLater(()->{
//更新JavaFXUI
});
}
//scheduleAtFixedRate(可运行函数、启动可运行前的等待时间、周期时间、时间单位)
//下面的线程将等待10秒,然后每1秒执行一次doBackground
scheduledCheck=scheduledExecutorService.scheduleAtFixedRate(背景,10,1,时间单位为秒);
}

以这种方式使用
while循环几乎总是一个坏主意。此外,我会首先尝试使用一个
按钮,按下该按钮后会查找插入的智能卡。是的,使用该按钮是一种解决方法,而不是一种解决方案,我希望像我使用swing实现的逻辑一样实现自动化。该建议不是一种解决方案。我想的更像是故障排除。我感觉自己像一个
初始化中的
循环不适合我。可能它应该是某种类型的
侦听器
,而不是一个循环,或者至少是一个
线程
。通常在JavaFX中使用JavaFX属性创建一个(或多个)模型类,可以在状态更改时进行更新。然后用那些更新UI的属性注册监听器。如果需要为长时间运行的进程使用后台线程,请将更新的线程包装到
Platform.runLater(…)
java命名约定中的属性