gpt4 book ai didi

java - 在 GUI 中与 JavaFX 网络服务交互

转载 作者:行者123 更新时间:2023-11-29 07:36:56 25 4
gpt4 key购买 nike

我正在从编写 Java Swing 应用程序过渡到 JavaFX,以编写基于 Java 的现代 GUI 应用程序。

我想知道创建基于网络的可重用线程服务的最佳方法。我对网络服务进行编码的方式是使用 Controller 类(通过 Net-beans GUI 从 FXML 生成)。我通过一个名为“transmitter”的私有(private)服务成员将线程逻辑放在这里。 ' 然后我通过开始/停止按钮的事件回调来连接开始/停止逻辑。
基于网络的线程是作为 javafx 服务实现的 - 我这样做是因为我想在目标地址发生变化时重新启动服务/线程。这似乎是代替独立任务的推荐方法。

网络服务现在非常简单,它所做的只是使用一些 GUI 小部件来配置数据包以每秒一次地传输到主机/端口。仅当主机/端口小部件更改时我才需要重新启动服务,但是如果网络服务正在运行,我想在不中断/重新启动 DatagramSocket 的情况下修改数据包。我有问题并需要一些指导的地方是:

  • 在一个线程中线程化网络线程的推荐方法是什么?
    基于 FXML 的应用程序?一个例子将不胜感激。
  • 我如何安全地传达来自 GUI 小部件的更改(通过它们的
    操作执行回调)到正在运行的服务类?

  • 下面显示的是我的 Controller 类中最相关的部分:
    /**
    * FXML Controller class
    *
    * @author johnc
    */
    public class OpMessageServerController implements Initializable {
    @FXML
    private Text mCurrentDateTimeText;
    @FXML
    private Label mApplicationStatus;
    @FXML
    private ComboBox<DiscreteStatus> mPofDS;
    @FXML
    private ComboBox<PhaseOfFlightFMS> mPofFMS;
    @FXML
    private ComboBox<DiscreteStatus> mTailNumberDS;
    @FXML
    private ComboBox<DiscreteStatus> mConfigTableDS;
    @FXML
    private ComboBox<DiscreteStatus> mDateTimeDS;
    @FXML
    private TextField mEpicPN;
    @FXML
    private TextField mConfigTablePNHash;
    @FXML
    private TextField mTailNumber;
    @FXML
    private ComboBox<DiscreteStatus> mTopLevelPNDS;
    @FXML
    private Button mStartStopButton;
    @FXML
    private ComboBox<String> mDLMUHostSpec;
    @FXML
    private CheckBox connectionStatusC1;
    @FXML
    private CheckBox wsuConnectionStatus;
    @FXML
    private CheckBox connectionStatusC4;
    @FXML
    private CheckBox connectionStatusC3;
    @FXML
    private CheckBox connectionStatusC2;
    @FXML
    private CheckBox dlmuwConnectionStatus;

    private Service<Void> transmitter;



    /**
    * Initializes the controller class.
    * @param url
    * @param rb
    */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
    mPofDS.setItems(FXCollections.observableArrayList(DiscreteStatus.values()));
    mPofDS.getSelectionModel().selectFirst();
    mPofFMS.setItems(FXCollections.observableArrayList(PhaseOfFlightFMS.values()));
    mPofFMS.getSelectionModel().selectFirst();
    mTailNumberDS.setItems(FXCollections.observableArrayList(DiscreteStatus.values()));
    mTailNumberDS.getSelectionModel().selectFirst();
    mConfigTableDS.setItems(FXCollections.observableArrayList(DiscreteStatus.values()));
    mConfigTableDS.getSelectionModel().selectFirst();
    mDateTimeDS.setItems(FXCollections.observableArrayList(DiscreteStatus.values()));
    mDateTimeDS.getSelectionModel().selectFirst();
    mTopLevelPNDS.setItems(FXCollections.observableArrayList(DiscreteStatus.values()));
    mTopLevelPNDS.getSelectionModel().selectFirst();
    // mDLMUHostSpec.setItems(FXCollections.observableArrayList(
    // FXCollections.observableArrayList("localhost:1234", "192.168.200.2:1234")));

    // add event handler here to update the current date/time label
    // this should also update the transmit datastructure
    final Timeline timeline = new Timeline(new KeyFrame(
    Duration.seconds(1), (ActionEvent event) -> {
    LocalDateTime currentDateTime = LocalDateTime.now();
    mCurrentDateTimeText.setText(currentDateTime.format(
    DateTimeFormatter.ofPattern("kk:mm:ss uuuu")));
    }));

    timeline.setCycleCount(Animation.INDEFINITE);
    timeline.play();

    // create a service.
    transmitter = new Service() {
    @Override
    protected Task createTask() {
    return new Task<Void>() {
    @Override
    protected Void call() throws InterruptedException {
    updateMessage("Running...");
    updateProgress(0, 10);
    DatagramSocket sock = null;
    while (!isCancelled()) {
    try {
    if (sock == null) {
    DatagramSocket sock = new DatagramSocket();
    }
    } catch (SocketException ex) {
    Logger.getLogger(OpMessageServerController.class.getName()).log(Level.SEVERE, null, ex);
    }
    //Block the thread for a short time, but be sure
    //to check the InterruptedException for cancellation
    OpSupportMessage opSupportMessage = new OpSupportMessage(
    DiscreteStatus.NormalOperation,
    PhaseOfFlightFMS.Cruise,
    DiscreteStatus.NormalOperation,
    "TAILNUM",
    DiscreteStatus.NormalOperation);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    String[] specParts = mDLMUHostSpec.getValue().split(":");
    if (specParts.length == 2) {
    try {
    opSupportMessage.write(bos);
    byte[] buff = bos.toByteArray();
    DatagramPacket packet = new DatagramPacket(
    buff, buff.length, InetAddress.getByName(
    specParts[0]), Integer.parseInt(specParts[1]));
    mSocket.send(packet);
    Thread.sleep(1000);
    } catch (IOException ex) {
    } catch (InterruptedException interrupted) {
    if (isCancelled()) {
    updateMessage("Cancelled");
    break;
    }
    }
    }
    }
    updateMessage("Cancelled");
    return null;
    }

    @Override
    protected void succeeded() {
    System.out.println("Scanning completed.");
    }

    @Override
    protected void failed() {
    System.out.println("Scanning failed.");
    }

    @Override
    protected void running() {
    System.out.println("Scanning started.");
    }

    @Override
    protected void cancelled() {
    System.out.println("Scanning cancelled.");
    }

    private void DatagramSocket() {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
    };
    }
    };

    mApplicationStatus.textProperty().bind(transmitter.messageProperty());

    };

    @FXML
    private void startStopButtonAction(ActionEvent event) {
    if (!transmitter.isRunning()) {
    transmitter.reset();
    transmitter.start();
    }
    }



    }

    最佳答案

    I would like to know the best approach to create a network based reusable threading service. The way I coded up the network service was to use a controller class (generated from the FXML via the Net-beans GUI). I put the threading logic here via a private Service member named 'transmitter' and I wired up the start/stop logic via the Start/Stop button's event callback.



    我谦虚地建议您将网络服务和 GUI Controller 作为单独的项目进行开发。

    我会将网络服务作为守护程序/后台线程在其自己的容器或虚拟机中运行。这种组织的优势在于它使您的服务器远离 JavaFX 事件循环和应用程序线程的变幻莫测。您需要设计您的服务以识别来自 Controller 的管理命令和/或中断请求。您可以将您的网络服务作为 REST 或任何您想要的方式开发,而无需考虑如何将其滚动到 JavaFX 应用程序线程中。

    然后,我会将 GUI Controller 作为单独的 GUI 应用程序在同一进程中运行,或者,如果需要远程管理,则在单独的 JVM 中运行(并使用 IPC 发送/接收管理消息)。

    TL;DR:如果是我,我会抵制将网络服务编程为 JavaFX 应用程序的诱惑。

    关于java - 在 GUI 中与 JavaFX 网络服务交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34537912/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com