You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Arduino UART发送的二维数组存入Qt QList<QString>并在QML显示

我来帮你一步步解决这个问题,看起来主要卡在三个地方:Arduino的数据传输格式、Qt端的数据解析与存储、QML的数据绑定。咱们逐个击破:

1. 修复Arduino的数据传输格式

你现在的Arduino代码直接连续打印double值,导致所有数据连在一起,Qt根本没法区分每个元素(比如1.012.02这种字符串,谁知道是两个数还是一个?)。所以必须给每个数据加分隔符,每行结束加换行标识一行完成:

void setup(){ 
  pinMode(LED_BUILTIN,OUTPUT); 
  analogWrite(LED_BUILTIN,255); 
  Serial.begin(115200); 
}

void loop(){ 
  double data[17][17]; 
  if(Serial.available()){
    delay(100); 
    for(int i=0; i<17; i++){ 
      for(int j=0; j<17; j++){ 
        data[i][j] = i+j+0.01; 
        sendData(data[i][j]); 
        delay(10); 
      }
      Serial.println(); // 每行结束发送换行,标记一行数据完成
    } 
  } 
  return; 
}

void sendData(double data){ 
  Serial.print(data); 
  Serial.print(","); // 每个数据后加逗号作为分隔符
}

2. 改进Qt端的串口数据解析与存储

你的readSerial函数目前只是读取数据并打印,没有做解析和存储。需要添加缓冲区累积数据,拆分分隔符,填充到QList<QString>并触发更新信号:

修改serial.h

添加缓冲区变量,调整Q_PROPERTY名称(和QML里的调用一致):

#include <QQmlApplicationEngine>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QtDebug>

class serial: public QObject {
    Q_OBJECT
    // 把Q_PROPERTY的名称改成model_data,和QML里的调用对应
    Q_PROPERTY(QList<QString> model_data READ text NOTIFY textChanged)
public:
    explicit serial(QQmlApplicationEngine *engine, QObject *parent = nullptr);
    ~serial();
    void setupSerial();
    Q_INVOKABLE QList<QString> text(){ return m_text; }
private slots:
    void readSerial();
private:
    QQmlApplicationEngine* m_engine;
    QSerialPort arduino;
    bool arduino_is_avaiable;
    QString portName;
    QByteArray m_buffer; // 新增:缓存串口数据,防止一次读不全
    QList<QString> m_text;
signals:
    void textChanged();
};
#endif // SERIAL_H

修改readSerial函数

实现数据解析、填充和更新通知:

void serial::readSerial(){
    // 把读取到的数据累积到缓冲区
    m_buffer += arduino.readAll();

    // 循环处理每一行数据(直到缓冲区里没有换行符)
    while (m_buffer.contains('\n')) {
        // 提取一行数据
        QByteArray line = m_buffer.left(m_buffer.indexOf('\n'));
        // 从缓冲区移除已处理的行
        m_buffer.remove(0, m_buffer.indexOf('\n') + 1);

        // 用逗号拆分一行里的所有数据
        QStringList rowElements = QString(line).split(',', Qt::SkipEmptyParts);
        if (rowElements.size() != 17) {
            qWarning() << "收到无效行,数据个数不对:" << rowElements.size();
            continue;
        }

        // 静态变量记录已收到的行数,满17行就重置并通知QML
        static int receivedRows = 0;
        if (receivedRows == 0) {
            m_text.clear(); // 开始接收新的17x17数组时清空旧数据
        }
        m_text.append(rowElements); // 把当前行的17个元素加入列表
        receivedRows++;

        if (receivedRows == 17) {
            receivedRows = 0;
            emit textChanged(); // 触发信号,通知QML数据已更新
            qDebug() << "已接收完整17x17数据,总元素数:" << m_text.size();
        }
    }
}

确保串口初始化正确

在setupSerial函数里完成串口配置和信号连接(如果之前没写的话):

void serial::setupSerial(){
    // 遍历可用串口,匹配Arduino的VID/PID(自行根据你的Arduino型号调整)
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()){
        if(info.vendorIdentifier() == 0x2341 && info.productIdentifier() == 0x0043){
            portName = info.portName();
            arduino_is_avaiable = true;
            break;
        }
    }

    if(arduino_is_avaiable){
        arduino.setPortName(portName);
        arduino.open(QSerialPort::ReadOnly);
        arduino.setBaudRate(QSerialPort::Baud115200);
        arduino.setDataBits(QSerialPort::Data8);
        arduino.setParity(QSerialPort::NoParity);
        arduino.setStopBits(QSerialPort::OneStop);
        arduino.setFlowControl(QSerialPort::NoFlowControl);
        // 连接串口就绪信号到读取槽函数
        connect(&arduino, &QSerialPort::readyRead, this, &serial::readSerial);
        qDebug() << "串口已打开:" << portName;
    } else {
        qDebug() << "未找到Arduino设备!";
    }
}

别忘了在serial的构造函数里调用setupSerial():

serial::serial(QQmlApplicationEngine *engine, QObject *parent) 
    : QObject(parent), m_engine(engine){
    setupSerial();
}

3. 修正QML的数据绑定

现在QML里的Text绑定已经是Serial.model_data[index],和我们修改的Q_PROPERTY名称一致,只要确保Repeater的model是17*17,索引就能对应到m_text里的每个元素:

import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    visible: true
    width: 17*square_size
    height: 17*square_size
    title: qsTr("17x17 Matrix Display")
    property int square_size: 30

    Grid {
        id: grid
        columns: 17
        Repeater{
            id: rpt
            model: 17*17
            Rectangle{
                width: square_size
                height: square_size
                border.color: "black"
                border.width: 1
                Text {
                    anchors.centerIn: parent
                    // 绑定到Serial的model_data列表,index对应每个矩形的位置
                    text: Serial.model_data[index] || "" // 为空时显示空字符串
                }
            }
        }
    }
}

关键注意点

  • 确保Arduino和Qt的串口波特率都是115200,参数一致(数据位、停止位、校验位)
  • Arduino的VID/PID需要根据你的实际型号调整(比如Nano是0x1A86,PID 0x7523)
  • 如果数据更新不及时,检查textChanged信号是否正确触发,QML会自动响应信号刷新UI

内容的提问来源于stack exchange,提问作者TrungPC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:04:48