Как отобразить значение 2D Array в QML из C ++, используя Repeater и GridView - PullRequest
1 голос
/ 26 января 2020

У меня проблема при отображении значения 2D-массива QString в QML из C ++

У меня есть данные и qmlRegisterType для использования в QML.

Это файл QML:

import QtQuick 2.12
import QtQuick.Window 2.2
import io.myserial 1.0
import QtQuick.Controls 2.3
Window {
    visible: true
    width: 8*square_size
    height: 8*square_size
    title: qsTr("Matrix LDR Value")
    property int  square_size: 50
    Grid {
        id: grid
        columns: 8
        Repeater{
            id: rpt
            model: 8*8
            Rectangle{
                width: square_size
                height: square_size
                border.color: "black"
                border.width: 1

                Text {
                    id: txt
                    anchors.centerIn: parent
                }
                MSerial{
                    onModelDataChanged:{
                        txt.text = Serial.model_data[i]
                    }
                }
            }
        }
    }
}

Это основной. cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "serial.h"
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);  

    qmlRegisterType<Serial>("io.myserial", 1, 0, "MSerial");

    QQmlApplicationEngine engine;

    Serial mySerial(&engine);
    engine.rootContext()->setContextProperty("Serial", &mySerial);

    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();
 }

serial.h

#ifndef SERIAL_H
#define SERIAL_H
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QQmlApplicationEngine>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QtDebug>
#include <QObject>
#include <QString>
#include <QString>
#include "toInt16.h"

class Serial: public QObject
{
    Q_OBJECT
    Q_PROPERTY(QList<QString> modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)

public:

    explicit Serial(QObject *parent = nullptr);

    QList<QString> modelData();

    Q_INVOKABLE void setModelData(const QList<QString> &modelData);
    void ReadSerial();

    void setUpSerial();
    QByteArray serialData;
    QSerialPort stm32;
    QString portName;
    QString buffer;
    bool isStm32Avaiable;
private slots:
    void readSerial();
signals:
    void modelDataChanged();

private:
    QList<QString> myModelData;

public slots:

};

#endif // SERIAL_H

serial. cpp

#include "serial.h"
#include "toInt16.h"



Serial::Serial(QObject *parent) : QObject(parent)
{
    setUpSerial();
}

QList<QString> Serial::modelData()
{
    return myModelData;
}


void Serial::setUpSerial(){
    buffer = "";
    isStm32Avaiable = false;
    portName = "";
    qDebug()<<"Num port: "<<QSerialPortInfo::availablePorts().length();

    foreach (const QSerialPortInfo &serialPortInfor,QSerialPortInfo::availablePorts()) {
        qDebug()<<"Has Vendo ID: "<<serialPortInfor.hasVendorIdentifier();
        if(serialPortInfor.hasVendorIdentifier()){
            qDebug()<<"Vendo ID: "<<serialPortInfor.vendorIdentifier();
        }
        qDebug()<<"Has Product ID: "<<serialPortInfor.hasProductIdentifier();
        if(serialPortInfor.hasProductIdentifier()){
            qDebug()<<"Product ID: "<<serialPortInfor.productIdentifier();
            portName = serialPortInfor.portName();
        }
        if(QSerialPortInfo::availablePorts().length() >0){
            isStm32Avaiable = true;
        }
    }
    if(isStm32Avaiable){
        stm32.setPortName(portName);
        stm32.open(QSerialPort::ReadWrite);
        stm32.setBaudRate(QSerialPort::Baud115200);
        stm32.setDataBits(QSerialPort::Data8);
        stm32.setParity(QSerialPort::NoParity);
        stm32.setStopBits(QSerialPort::OneStop);
        stm32.setFlowControl(QSerialPort::NoFlowControl);
        QObject::connect(&stm32, SIGNAL(readyRead()),this,SLOT(readSerial()));


    }else{

        qDebug()<<"warning: Port Error . Couldn't find kit";
    }
}

void Serial::setModelData(const QList<QString> &modelData)
{
    if (modelData == myModelData)
        return;

    myModelData = modelData;
    emit modelDataChanged();
}


void Serial::ReadSerial()
{
    serialData.clear();
    serialData = stm32.readAll();
    QByteArray buffer;
    qDebug()<< "Serial Data: "<<serialData;
    buffer = serialData;//.split(',');
    // QStringList buffer2;

    //uint16_t data[64];
    union INT_TO_BYTE receivedData[64];

    for(int i=0; i<64; i++){
        receivedData[i].b[0] = buffer.data()[i*2];
        receivedData[i].b[1] = buffer.data()[i*2+1];
        receivedData[i].i = (uint16_t)receivedData[i].b[0]|(uint16_t)receivedData[i].b[1]<<8;
        qDebug() << "This is data "<<i<<" "<<receivedData[i].i;
        myModelData.append(QString::number(receivedData[i].i));
    }
    //setModelData(myModelData);
    emit modelDataChanged();
}

toInt16.h

#ifndef TOINT16_H
#define TOINT16_H

#include <QTextCodec>

union INT_TO_BYTE
{
    uint16_t i;
    char b[2];
};
//union INT_TO_BYTE receivedData[128];



#endif // TOINT16_H

Я получил данные, но не могу отобразить их в QML при изменении данных. Я установил это изменение 1view / se c. Мой лог c: при каждом изменении данных QML отображает новые данные

1 Ответ

2 голосов
/ 26 января 2020

В вашем коде я вижу следующие ошибки:

  • Или вы регистрируете тип с помощью qmlRegisterType или устанавливаете его как contextProperty, а не оба. Я рекомендую вам проверить Выбор правильного метода интеграции между C ++ и QML .

  • В вашем репитере вы создаете N MySerial, но вы можете иметь только 1, идея в том, что вы создаете MySerial, и информация передается в модель.

  • Не используйте QList<QString>, но QStringList.

  • Ваш данные не должны быть записаны из QML, поэтому для свойства modelData не обязательно иметь значение Writeble.

Учитывая вышеизложенное и избегая части декодирования данных, поскольку я не знаю формат, который заменит его, создавая случайные данные, решение является следующим:

serial. cpp

#ifndef SERIAL_H
#define SERIAL_H

#include <QObject>
#include <QSerialPort>

class Serial : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QStringList modelData READ modelData NOTIFY modelDataChanged)
public:
    explicit Serial(QObject *parent = nullptr);
    QStringList modelData() const;
Q_SIGNALS:
    void modelDataChanged();
private Q_SLOTS:
    void readSerial();
private:
    void setUpSerial();
    QStringList m_modelData;
    bool isStm32Avaiable;
    QString portName;
    QSerialPort stm32;
};

#endif // SERIAL_H

serial. cpp

#include "serial.h"
#include "toInt16.h"

#include <QSerialPortInfo>
#include <QDebug>

Serial::Serial(QObject *parent) : QObject(parent){
    m_modelData.reserve(64);
    setUpSerial();
}

QStringList Serial::modelData() const{
    return m_modelData;
}

void Serial::setUpSerial(){
    isStm32Avaiable = false;
    portName = "";
    qDebug()<<"Num port: "<<QSerialPortInfo::availablePorts().length();
    for (const QSerialPortInfo &serialPortInfor : QSerialPortInfo::availablePorts()) {
        qDebug()<<"Has Vendo ID: "<<serialPortInfor.hasVendorIdentifier();
        if(serialPortInfor.hasVendorIdentifier()){
            qDebug()<<"Vendo ID: "<<serialPortInfor.vendorIdentifier();
        }
        if(serialPortInfor.hasProductIdentifier()){
            qDebug()<<"Product ID: "<<serialPortInfor.productIdentifier();
            portName = serialPortInfor.portName();
        }
        if(!QSerialPortInfo::availablePorts().isEmpty()){
            isStm32Avaiable = true;
            break;
        }
    }
    if(isStm32Avaiable){
        stm32.setPortName(portName);
        stm32.open(QSerialPort::ReadWrite);
        stm32.setBaudRate(QSerialPort::Baud115200);
        stm32.setDataBits(QSerialPort::Data8);
        stm32.setParity(QSerialPort::NoParity);
        stm32.setStopBits(QSerialPort::OneStop);
        stm32.setFlowControl(QSerialPort::NoFlowControl);
        connect(&stm32, &QIODevice::readyRead, this, &Serial::readSerial);
    }else{
        qDebug()<<"warning: Port Error . Couldn't find kit";
    }
}

void Serial::readSerial(){
    m_modelData.clear();
    // FIXME
    static int counter;
    for(int i=0; i<64; i++){
        m_modelData.append(QString::number(counter));
        counter++;
    }
    //
    emit modelDataChanged();
}

main. cpp

#include "serial.h"

#include <QGuiApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    qmlRegisterType<Serial>("io.myserial", 1, 0, "MSerial");
    QGuiApplication app(argc, argv);

    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.Window 2.12
import io.myserial 1.0

Window {
    visible: true
    width: 8*square_size
    height: 8*square_size
    title: qsTr("Matrix LDR Value")
    property int  square_size: 50
    MSerial{
        id: serial
    }
    Grid {
        columns: 8
        Repeater{
            model: serial.modelData
            Rectangle{
                width: square_size
                height: square_size
                border.color: "black"
                border.width: 1
                Text {
                    id: txt
                    anchors.centerIn: parent
                    text: model.modelData
                }
            }
        }
    }
}
...