I am working on a barcode scanning project. I use a barcode scanner to scan barcodes and the scanner communicates with my laptop via bluetooth. The bluetooth connection is emulated as the serial port communication.
I have developed a Java desktop application to retrieve the barcodes scanned and display them. I use Javafx for UI and the open source library JSSC(Java Simple Serial Connector) to listen to the serial port and retrieve the barcodes scanned. However, when a JSSC serialPort is added/started, a new thread is created. This new thread listens to the serial port and retrieves the barcodes scanned. What I want is to display the scanned barcodes on Javafx UI, which the barcodes retrieved in the JSSC listener thread have to be sent back to the parent Javafx application thread.
I explored the javafx.concurrent Package but found that JSSC wraps the thread creation into its own class and I don’t have control over it. Could someone suggest a solution for it? Here is my code snippet to start the JSSC listener within Javafx controller. Basically, how can I set buffer back to the FXML label variable barcode?
Really appreciate it in advance!
public class BarcodeScanningController {
@FXML
private Label barcode;
private static SerialPort serialPort;
@FXML
void initialize() {
serialPort = new SerialPort("COM5");
try {
if (serialPort!=null && serialPort.isOpened ()) {
serialPort.closePort();
}
serialPort.openPort();
serialPort.setParams(SerialPort.BAUDRATE_9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
int mask = SerialPort.MASK_RXCHAR + SerialPort.MASK_CTS + SerialPort.MASK_DSR;//Prepare mask
serialPort.setEventsMask(mask);//Set mask
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN |
SerialPort.FLOWCONTROL_RTSCTS_OUT);
serialPort.addEventListener(new PortReader(),SerialPort.MASK_RXCHAR);
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
private class PortReader implements SerialPortEventListener {
private String buffer;
@Override
public void serialEvent(SerialPortEvent event) {
if(event.isRXCHAR()){
try {
buffer = serialPort.readString();
System.out.println(buffer);
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
}
}
Add a Consumer<String>
to your PortReader
class:
private class PortReader implements SerialPortEventListener {
private final Consumer<String> textHandler ;
PortReader(Consumer<String> textHandler) {
this.textHandler = textHandler ;
}
@Override
public void serialEvent(SerialPortEvent event) {
if(event.isRXCHAR()){
try {
String buffer = serialPort.readString();
textHandler.accept(buffer);
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
}
And then just replace
serialPort.addEventListener(new PortReader(),SerialPort.MASK_RXCHAR);
with
serialPort.addEventListener(
new PortReader(buffer -> Platform.runLater(() -> barCode.setText(buffer))),
SerialPort.MASK_RXCHAR);