QtQuick 串口通讯demo
SerialPortHandler.h
#ifndef SERIALPORTHANDLER_H #define SERIALPORTHANDLER_H #include <QObject> #include <QSerialPort> #include <QSerialPortInfo> class SerialPortHandler : public QObject { Q_OBJECT Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged) Q_PROPERTY(QString receivedData READ receivedData NOTIFY dataReceived) public: explicit SerialPortHandler(QObject *parent = nullptr); Q_INVOKABLE void openSerialPort(const QString &portName, int baudRate); Q_INVOKABLE void closeSerialPort(); Q_INVOKABLE void sendData(const QString &data); Q_INVOKABLE QStringList availablePorts(); bool connected() const; QString receivedData() const; signals: void connectedChanged(bool connected); void dataReceived(const QString &data); void errorOccurred(const QString &error); private slots: void handleReadyRead(); void handleError(QSerialPort::SerialPortError error); private: QSerialPort *m_serialPort; QString m_receivedData; bool m_connected; }; #endif // SERIALPORTHANDLER_H
SerialPortHandler.cpp
#include "SerialPortHandler.h" #include <QDebug> SerialPortHandler::SerialPortHandler(QObject *parent) : QObject(parent), m_connected(false) { m_serialPort = new QSerialPort(this); connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortHandler::handleReadyRead); connect(m_serialPort, &QSerialPort::errorOccurred, this, &SerialPortHandler::handleError); } void SerialPortHandler::openSerialPort(const QString &portName, int baudRate) { if(m_serialPort->isOpen()) { closeSerialPort(); } m_serialPort->setPortName(portName); m_serialPort->setBaudRate(baudRate); m_serialPort->setDataBits(QSerialPort::Data8); m_serialPort->setParity(QSerialPort::NoParity); m_serialPort->setStopBits(QSerialPort::OneStop); m_serialPort->setFlowControl(QSerialPort::NoFlowControl); if (m_serialPort->open(QIODevice::ReadWrite)) { m_connected = true; emit connectedChanged(true); } else { emit errorOccurred(tr("打开串口失败: ") + m_serialPort->errorString()); } } void SerialPortHandler::closeSerialPort() { if (m_serialPort->isOpen()) { m_serialPort->close(); m_connected = false; emit connectedChanged(false); } } void SerialPortHandler::sendData(const QString &data) { // if (m_serialPort->isOpen()) { // m_serialPort->write(data.toUtf8()); // if (!m_serialPort->waitForBytesWritten(1000)) { // emit errorOccurred(tr("发送超时")); // } // } } QStringList SerialPortHandler::availablePorts() { QStringList ports; for (const QSerialPortInfo &info : QSerialPortInfo::availablePorts()) { ports.append(info.portName()); } return ports; } bool SerialPortHandler::connected() const { return m_connected; } QString SerialPortHandler::receivedData() const { return m_receivedData; } void SerialPortHandler::handleReadyRead() { QByteArray data = m_serialPort->readAll(); m_receivedData = QString::fromUtf8(data); emit dataReceived(m_receivedData); } void SerialPortHandler::handleError(QSerialPort::SerialPortError error) { if (error != QSerialPort::NoError) { emit errorOccurred(m_serialPort->errorString()); closeSerialPort(); } }
main.cpp
#include "SerialPortHandler.h" #include <QGuiApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); // 注册串口处理类 qmlRegisterType<SerialPortHandler>("SerialPort", 1, 0, "SerialPortHandler"); QQmlApplicationEngine engine; const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
main.qml
import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 import SerialPort 1.0 ApplicationWindow { width: 600 height: 400 visible: true title: "Qt Serial Port Demo" SerialPortHandler { id: serialPort onDataReceived: { if(receivedText.lineCount>30){ // 按换行符分割文本 var lines = receivedText.text.split('\n'); // 删除第一行(如果存在) if (lines.length > 1) { lines.shift(); // 移除数组第一个元素 receivedText.text = lines.join('\n'); } else { receivedText.text = ""; // 只剩一行时清空 } } receivedText.append("接收: " + data) } onErrorOccurred: { statusLabel.text = "错误: " + error } } ColumnLayout { anchors.fill: parent anchors.margins: 10 // 串口选择 RowLayout { Label { text: "选择串口:" } ComboBox { id: portComboBox Layout.fillWidth: true model: serialPort.availablePorts() } Label { text: "波特率:" } ComboBox { id: baudComboBox model: [9600, 19200, 38400, 57600, 115200] currentIndex: 4 // 默认115200 } Button { text: serialPort.connected ? "断开" : "连接" onClicked: { if(serialPort.connected) { serialPort.closeSerialPort() } else { serialPort.openSerialPort(portComboBox.currentText, baudComboBox.currentText) } } } } // 发送区域 GroupBox { title: "发送数据" Layout.fillWidth: true ColumnLayout { TextField { id: sendField Layout.fillWidth: true placeholderText: "输入要发送的数据" onAccepted: sendButton.clicked() } Button { id: sendButton text: "发送" onClicked: { if(sendField.text.length > 0) { serialPort.sendData(sendField.text) receivedText.append("发送: " + sendField.text) sendField.clear() } } } } } // 接收区域 GroupBox { title: "接收数据" Layout.fillWidth: true Layout.fillHeight: true ScrollView { anchors.fill: parent TextArea { id: receivedText readOnly: true wrapMode: Text.Wrap } } } // 状态栏 Label { id: statusLabel Layout.fillWidth: true text: serialPort.connected ? "已连接: " + portComboBox.currentText + " @ " + baudComboBox.currentText + " bps" : "未连接" } } }

浙公网安备 33010602011771号