How to Create a GUI Java Serial Port Terminal (Swing + jSerialComm)
Overview
Build a simple cross-platform GUI terminal that lists ports, opens a port, sends typed text, and displays incoming data using Swing for the UI and jSerialComm for serial I/O.
Dependencies
- jSerialComm (add to Maven/Gradle or include jSerialComm.jar)
- Maven example:
Code
com.fazecast jSerialComm 2.9.2
- Maven example:
- Java 8+ (adjust native-access flags for Java 24+ if needed)
Key design points
- Use SerialPort.getCommPorts() to list ports.
- Open port and set parameters (baud, data bits, stop bits, parity).
- Use an event-driven SerialPortDataListener to avoid polling.
- Perform serial I/O off the EDT (Swing event thread); update Swing components on EDT using SwingUtilities.invokeLater.
- Close port on exit.
Minimal working example
- Single-window Swing UI with:
- JComboBox for port selection
- JComboBox for baud rate
- JTextArea (read-only) for received data
- JTextField for input and a Send button
- Connect/Disconnect button
Example code (concise, ready-to-run — replace package and dependency as needed):
java
import com.fazecast.jSerialComm.; import javax.swing.; import java.awt.; import java.awt.event.; public class SerialTerminal extends JFrame { private SerialPort port; private JComboBox<String> portBox, baudBox; private JTextArea recvArea; private JTextField sendField; private JButton connectBtn, sendBtn; public SerialTerminal() { super(“Java Serial Terminal”); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(700,400); setLayout(new BorderLayout()); // Top panel JPanel top = new JPanel(); portBox = new JComboBox<>(); for (SerialPort p : SerialPort.getCommPorts()) portBox.addItem(p.getSystemPortName()); baudBox = new JComboBox<>(new String[]{“9600”,“19200”,“38400”,“57600”,“115200”}); connectBtn = new JButton(“Connect”); top.add(new JLabel(“Port:”)); top.add(portBox); top.add(new JLabel(“Baud:”)); top.add(baudBox); top.add(connectBtn); add(top, BorderLayout.NORTH); // Center recvArea = new JTextArea(); recvArea.setEditable(false); add(new JScrollPane(recvArea), BorderLayout.CENTER); // Bottom JPanel bottom = new JPanel(new BorderLayout()); sendField = new JTextField(); sendBtn = new JButton(“Send”); bottom.add(sendField, BorderLayout.CENTER); bottom.add(sendBtn, BorderLayout.EAST); add(bottom, BorderLayout.SOUTH); // Actions connectBtn.addActionListener(e -> { if (port == null || !port.isOpen()) openPort(); else closePort(); }); sendBtn.addActionListener(e -> sendText()); sendField.addActionListener(e -> sendText()); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { closePort(); } }); } private void openPort() { String name = (String)portBox.getSelectedItem(); int baud = Integer.parseInt((String)baudBox.getSelectedItem()); port = SerialPort.getCommPort(name); port.setBaudRate(baud); port.setNumDataBits(8); port.setNumStopBits(SerialPort.ONE_STOP_BIT); port.setParity(SerialPort.NO_PARITY); if (!port.openPort()) { JOptionPane.showMessageDialog(this, “Failed to open port”); port = null; return; } port.addDataListener(new SerialPortDataListener() { public int getListeningEvents() { return SerialPort.LISTENING_EVENT_DATA_AVAILABLE; } public void serialEvent(SerialPortEvent ev) { if (ev.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) return; byte[] buf = new byte[port.bytesAvailable()]; int n = port.readBytes(buf, buf.length); if (n > 0) { String s = new String(buf, 0, n); SwingUtilities.invokeLater(() -> recvArea.append(s)); } } }); connectBtn.setText(“Disconnect”); recvArea.append(“Opened “ + name + ” @ “ + baud + ” “); } private void closePort() { if (port != null) { port.removeDataListener(); port.closePort(); recvArea.append(“Port closed “); port = null; } connectBtn.setText(“Connect”); } private void sendText() { if (port == null || !port.isOpen()) { JOptionPane.showMessageDialog(this,“Not connected”); return; } String s = sendField.getText(); if (s == null) return; byte[] out = (s + ” “).getBytes(); port.writeBytes(out, out.length); sendField.setText(””); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> { SerialTerminal t = new SerialTerminal(); t.setVisible(true); }); } }
Tips & troubleshooting
- Run with appropriate permissions (Linux: add user to dialout/tty groups).
- If using Java 24+, launch with –enable-native-access=com.fazecast.jSerialComm.
- If no ports appear, check cable/USB drivers and device manager.
- Use event-based listener rather than polling for efficiency.
- If binary data required, handle encoding/byte framing instead of appending strings.
If you want, I can provide a version with line-ending options, hex view mode, or a Maven/Gradle project skeleton.
Leave a Reply