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

huangapple go评论88阅读模式
英文:

JavaFX controller, implementing non-graphic events and background state machine

问题

我不久前开始学习JavaFX,并且正在尝试从Swing切换到JavaFX。我遇到了一些逻辑实现问题,使用JavaFX无法像使用Swing时那样轻松解决。

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

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

@Override
public void initialize(URL url, ResourceBundle rb) {
    if (no_error) {
        转到第一个页面
    } else {
        转到故障页面
    }
}

我想要实现的第一件事是等待,因为其中一些驱动程序和设备不会立即工作,例如,在每个设备上等待1秒的情况下等待10个周期。

@Override
public void initialize(URL url, ResourceBundle rb) {
    while (true) {
        if (no_error) {
            转到第一个页面
        } else {
            if (timeout_expired) {
                转到故障页面
            } else {
                等待
                增加超时时间
            }
        }
    }
}

我知道initialize方法的目的不是这个,上面的代码也不是一个解决方案,我更希望找到类似于AsyncTask中的doInBackground函数的解决方案。

此外,在这个应用程序的控制器中,我想要实现一些与图形无关的事件,比如读取智能卡。如何从智能卡驱动程序连接事件,当它读取卡片数据时,将数据发送到控制器中实现的函数,就像下面这样的函数?

public void controller_smart_card_read(SmartCard smart_card){
    //从数据库中检查卡片是否有效
    //显示结果
}

另外,在某些场景中,我想要实现一个不活动事件。如果一段时间内没有事件(无论是图形事件还是设备事件),例如,就返回到第一个页面。

总之,有没有一种方式可以从独立的软件模块访问和触发控制器?还有没有一种在场景和控制器正在运行时实现类似doInBackground()的函数的方法?

英文:

I started learning about JavaFX a short time ago and I am trying to switch from Swing to JavaFX. I ran into some logic implementation problem that I cannot think of a solution with JavaFX that I easily solved using Swing.

The application that I developed is huge, containing multiple already developed software modules, that interact with the graphics at some point. For example, in the application I have a smart card reader that, when a card is read on that reader and the operator is authenticating with a smart card, it displays on the graphic that a valid card is read, it display a green card icon and lets the operator enters his password. There are multiple drivers like the smart card reader and all of them generate events also with their status, are they working or not. In the current solution all modules communicate with central main software that can call functions for the Swing graphics.

The application starts with initializing a page, and when all of the devices are working and there is no error, I am showing the first page of the application. If any of them has an error, I am showing the error page. I designed some fxml and connect them with their own controller. In the controller of the initializing page in the method should look something like this:

@Override
public void initialize(URL url, ResourceBundle rb) {
    if(no_error){
        go to first page
    }else{
        go to out of order page
    }
}

The first thing that I want to implement is to wait, because some of the drivers and devices won't work instantly, for example wait for 10 cycles with timeout of 1 second on each of them.

@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
            }
        }
    }
}

I know that purpose of the initialize method is not for this and the above code is not a solution, I am looking more for a function like doInBackground from the AsyncTask.

Also, in this application in the controller, I want to implement events that are not graphic related like the reading of the smart card. How to connect the event from the driver for the smart card, when it reads card data to send that data to a function implemented in the controller like the one below?

public void controller_smart_card_read(SmartCard smart_card){
    //Check if valid card from DB
    //Display result
}

Also, in some scene I want to implement an inactivity event. If there are no events for a longer period of time (both graphical and from the devices), go back to the first page for example.

To summarize this, is there a way a controller is accessed and triggered from an independent software module, and is there a way to implement a doInBackground() function while scene and controller is up and running?

答案1

得分: 1

创建一个后台线程来执行此功能,并使用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 = () -> {
    // 执行后台任务,例如检查卡片读取器
    if(devices_ready && successful_card_read)
      Platform.runLater(() -> {
        // 更新JavaFX的UI
      });
  }
  // 使用scheduleAtFixedRate(Runnable function, 初始延迟时间, 循环周期, 时间单位) 
  // 下面的线程将会等待10秒,然后每1秒执行一次doBackground
  scheduledCheck = scheduledExecutorService.scheduleAtFixedRate(doBackground, 10, 1, TimeUnit.SECONDS);
}
英文:

Create a background thread to do this functionality and use the Platform.runLater to update the UI.

For Example

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

ScheduledExecutorService scheduledExecutorService;
ScheduledFuture&lt;?&gt;       scheduledCheck;

public void start(Stage base) {

  base.setOnCloseRequest(
  scheduledExecutorService.shutdownNow();

  );

  scheduledExecutorService = Executors.newScheduledThreadPool(1);

  Runnable doBackground = () -&gt; {
    //Do background tasks i.e. check card reader
    if(devices_ready &amp;&amp; successful_card_read)
      Platform.runLater(() -&gt; {
        //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);
}

huangapple
  • 本文由 发表于 2020年8月29日 04:31:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/63640526.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定