What is JavaFX And How Does A Simple COM Port Terminal Works?
In life, a built-in developer, there is often a need for interaction with the serial port.
And let the RS-232 is almost completely superseded by modern means, UART seems to be going nowhere.
- Most modules (WI-FI, IoT, etc.), Demo/single-board or work on board UART.
Terminal programs are huge, the most notable are Putty and terminal v1.9b
They do an excellent job, but the difficulties start when there is more than one open connection.
- Switching and searching for the desired window takes a lot of time.
Then the idea arose, why not write a terminal where each connection will be in a separate tab, and each incoming packet will signal it. I’m sure it’s more convenient than 4 terminals scattered across different screens.
- The choice was between node WebKit, Qt, and JavaFX. Node Webkit frightened with possible voracity, Qt is long in development/debugging.
And by the evening there was a relatively working project.
Probably there is no point in spreading all the code here.
- The project is on the Git.
We will present the most interesting part in my opinion:
public class ConnectionData { @FXML // - field with the incoming data public TextArea receiveData; @FXML // - for sending data public TextField sendData; @FXML // - (send button, bind with sendDataProperty, is active if the field is not empty) public button sendButton; // bind private StringProperty sendDataProperty = new SimpleStringProperty (""); // queue BlockingQueue <String> rxDataQueue = new LinkedBlockingQueue <> (); @FXML public void initialize () { , SendData.textProperty () bindBidirectional (sendDataProperty); , SendButton.disableProperty () bind (sendDataProperty.isEmpty ()); The task <Void> task = new The task <Void> () { @override public Void call () throws Exception {// read to read data, new data creates a new MessageConsumer Platform.runLater (() -> new MessageConsumer (rxDataQueue, receiveData, rxDataQueue.size ()). Start ()); return null; } };}; new topic (task) .start (); } public class MessageConsumer extends AnimationTimer { private final BlockingQueue <String> messageQueue; closed final TextArea textArea; private int messagesReceived = 0; public MessageConsumer (BlockingQueue <String> messageQueue, TextArea textArea, int numMessages) { this.messageQueue = messageQueue; this.textArea = textArea; } @override public void handle (long) { List <String> messages = new ArrayList <> (); messagesReceived + = messageQueue.drainTo (messages); messages.forEach (msg -> textArea.appendText (msg)); } } public button getPropertySendButton () { return sendButton; } public String getSendDataProperty () { String sendBuff = sendDataProperty.get (); sendDataProperty.set (""); return sendBuff; } public void clearReceiveData () {// - on the flush button on the form receiveData.textProperty () SetValue (""); } public void setReceiveData (byte [] buffer) {// the received data from the port is placed here try { rxDataQueue.add (new line (buffer, "UTF-8")); } catch (UnsupportedEncodingException ex) { System.err.print (ex); } } }
The form class for outputting the received form is TextField (send data).
If you directly write data to the buffer and send it directly to TextField, a nullException will appear very soon. they are in different threads.
- For this, as it is not difficult to guess, the queue is used – BlockingQueue rxDataQueue.
The data is received with SerialPort (jssc) and placed in the queue via the setReceiveData call.
The task will take the received element and after sending it will remove it from the queue.
What we want to get further and what is planned from the functional:
- Probably need to save configs on ports
- SSH client (flexible and intuitive!)
- Add a custom color to the tabs
- Bring the interface to a nice view, CSS, JFoenix