从另一个实现 SerialPortEventListener(Java FX、FXML)的 class 更新 GUI
Updating GUI from another class which implements SerialPortEventListener (Java FX, FXML)
我正在制作一个使用串行通信的应用程序。在那个 class 的 SerialEvent
方法中,我正在等待来自 COM 端口的输入,然后我想将它传递给 .fxml
屏幕的控制器 class。
输入将始终为 8 个字节,并且它在该线程内正常工作(我读取输入并将其打印到输出,我看到 String
是正确的)。但是,当我尝试将它 "in real time" 传递给控制器 class 时,我遇到了问题。
如果我直接传递它,它确实会收到它,但我以后不能调用任何东西(不是在 FX 应用程序线程异常上),我知道我不能那样做,我需要使用Platform.runLater
或 similair 解决方案,但如果我那样使用它,我的控制器 class 永远不会收到该输入,我尝试更新的 textField
保持空白。
我将部分代码复制到这里,希望有人告诉我我做错了什么。
另一个CLASS
的串行事件方法
@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);
}
}
}
控制器的输入方法CLASS
@Override
public void getInputString(String input) {
firstSerialNumberField.setText(input);
}
以这种方式使用时,我的 firstSerialNumberField
永远不会得到该输入。
---编辑---
SERIALPORTLISTENER的SETCONTROLLER方法CLASS
public void setController(SerialController controller) {
this.controller = controller;
}
在屏幕处理程序中初始化屏幕CLASS
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();
您正在将对 inputText
的引用传递给控制器中的(命名不当的)getInputText()
方法。 inputText
大概是 class 中实现端口侦听器的一个字段。然而,一旦你传递它,你就将它设置回一个空字符串:
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));
}
我正在制作一个使用串行通信的应用程序。在那个 class 的 SerialEvent
方法中,我正在等待来自 COM 端口的输入,然后我想将它传递给 .fxml
屏幕的控制器 class。
输入将始终为 8 个字节,并且它在该线程内正常工作(我读取输入并将其打印到输出,我看到 String
是正确的)。但是,当我尝试将它 "in real time" 传递给控制器 class 时,我遇到了问题。
如果我直接传递它,它确实会收到它,但我以后不能调用任何东西(不是在 FX 应用程序线程异常上),我知道我不能那样做,我需要使用Platform.runLater
或 similair 解决方案,但如果我那样使用它,我的控制器 class 永远不会收到该输入,我尝试更新的 textField
保持空白。
我将部分代码复制到这里,希望有人告诉我我做错了什么。
另一个CLASS
的串行事件方法@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);
}
}
}
控制器的输入方法CLASS
@Override
public void getInputString(String input) {
firstSerialNumberField.setText(input);
}
以这种方式使用时,我的 firstSerialNumberField
永远不会得到该输入。
---编辑---
SERIALPORTLISTENER的SETCONTROLLER方法CLASS
public void setController(SerialController controller) {
this.controller = controller;
}
在屏幕处理程序中初始化屏幕CLASS
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();
您正在将对 inputText
的引用传递给控制器中的(命名不当的)getInputText()
方法。 inputText
大概是 class 中实现端口侦听器的一个字段。然而,一旦你传递它,你就将它设置回一个空字符串:
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));
}