从另一个实现SerialPortEventListener(Java FX,FXML)的类更新GUI

时间:2016-09-04 10:24:06

标签: com serial-port javafx-8

我正在制作一个使用串行通信的应用程序。在该类的SerialEvent方法中,我正在等待来自COM端口的输入,然后我想将其传递给.fxml屏幕的控制器类。 输入将始终为8个字节,并且它在该线程内正常工作(我读取输入并将其打印到输出,我看到String是正确的)。但是,当我试图实时传递它时#34;对于控制器类,我有一个问题。

如果我直接传递它,它会收到它,但我以后不能调用任何东西(不是FX应用程序线程异常),我知道我不能这样做,我需要使用Platform.runLater或similair解决方案,但如果我这样使用它,我的控制器类永远不会收到该输入,我试图更新的textField保持空白。

我会在这里复制部分代码,我希望有人能告诉我我做错了什么。

另一类的SERIALEVENT方法

@Override
public void serialEvent(SerialPortEvent spe) {

    if (spe.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
        try {
            byte singleData = (byte) input.read();

            logText = new String(new byte[]{singleData});
            bytes.add(logText);
            if(bytes.size() == 8) {

                for (int i = 0; i < bytes.size(); i++) {
                    inputText += bytes.get(i);
                }

                if(inputText.length() == 8) {

                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            controller.getInputString(inputText);
                        }
                    });
                }                           

                bytes.clear();
                inputText = "";
            }
        } catch (Exception e) {
            logText = "Failed to read data. (" + e.toString() + ")";
            controller.getInputString(logText);
        }
    }
}

控制器类的GETINPUT方法

@Override
public void getInputString(String input) {

    firstSerialNumberField.setText(input);
}

以这种方式使用时,我的firstSerialNumberField永远不会得到那个输入。

--- --- EDIT

SERIALPORTLISTENER CLASS的SETCONTROLLER方法

    public void setController(SerialController controller) {

        this.controller = controller;
}

屏幕处理程序类中的初始化屏幕

    serialCommunication = new SerialCommunication(this);

loader = new FXMLLoader();
loader.setLocation(getClass().getResource(path));
pane = loader.load(getClass().getResource(path).openStream());
serialController = (SerialController) loader.getController();
serialController.setScreenHandler(this);
serialController.setSerialCommunication(serialCommunication); 
serialCommunication.setController(serialController);
parent = loader.getRoot();
stage = new Stage();
stage.setScene(new Scene(parent));
stage.setTitle(title);
stage.setResizable(false);
stage.sizeToScene();
stage.centerOnScreen();
stage.initModality(Modality.APPLICATION_MODAL);
stage.showAndWait();

1 个答案:

答案 0 :(得分:0)

您正在将inputText的引用传递给控制器​​中的(不恰当命名的)getInputText()方法。 inputText可能是实现端口侦听器的类中的一个字段。但是,只要您传递它,然后将其设置回空字符串:

        if(inputText.length() == 8) {

            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    controller.getInputString(inputText);
                }
            });
        }                           

        bytes.clear();
        inputText = "";

由于正在从多个线程访问inputText,因此无法保证将发生的事情是:首先执行controller.getInputText(inputText),还是首先执行inputText = "";。因此,您最终可能会将文本字段设置为空字符串。

我认为你打算做的是:

        if(inputText.length() == 8) {

            final String numberFieldText = inputText ;

            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    controller.getInputString(numberFieldText);
                }
            });
        }   

或更简洁:

        if(inputText.length() == 8) {

            final String numberFieldText = inputText ;

            Platform.runLater(() -> controller.getInputString(numberFieldText));
        }