Reputation: 57
I have problem when display value of 2D array QString on QML from C++
I have data and a qmlRegisterType to use on QML.
This is QML file:
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]
}
}
}
}
}
}
This is main.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
I received data but I cannot display it on QML whenever data is changed. I set it change 1view/sec. My logic is: Whenever data change, QML display new data
Upvotes: 1
Views: 680
Reputation: 244132
In your code I see the following errors:
Or you register a type with qmlRegisterType or set it as contextProperty, not both. I recommend you check Choosing the Correct Integration Method Between C++ and QML.
In your repeater you are creating N MySerial but you can only have 1, the idea is that you create a MySerial and the information is passed to the model.
Do not use QList<QString>
but QStringList
.
Your data should not be written from QML so it is not necessary for the modelData property to be Writeble.
Considering the above and avoiding the part of the decoding of the data since I do not know the format that will replace it creating random data the solution is the following:
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
}
}
}
}
}
Upvotes: 2