I receive a 2D array from UART that sent from Arduino. I can show it in debug, but I can not save it in a QList variant to set text for matrix of rectangle in QML.
I want to show text on QML each rectangle.
How I can do?
This is Arduino code. I send 2d array 17x17
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);
}
}
}
return;
}
void sendData(double data){
Serial.print((data));
}
This is readSerial function:
void serial::readSerial(){
serialData = arduino.readAll();
qDebug()<< serialData <<"\n";
}
QML file:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 17*square_size
height: 17*square_size
title: qsTr("Hello World")
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
text: Serial.model_data[index]
}
}
}
}
}
serial.h:
#include <QQmlApplicationEngine>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QtDebug>
class serial: public QObject
{
Q_OBJECT
Q_PROPERTY(QList<QString> text 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;
/* Varian of Arduino*/
QSerialPort arduino;
bool arduino_is_avaiable;
QString portName;
QByteArray serialData;
/*Varian of text*/
QList<QString> m_text;
signals:
void textChanged();
public slots:
};
#endif // SERIAL_H
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "serial.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
serial myserial(&engine);
engine.rootContext()->setContextProperty("Serial", &myserial);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
I think you are missing the property on the Serial
class to read the data: text: Serial.model_data[index]
. The fastest solution to get something on screen would be to add that property and fill it as follows:
Serial.h (I left some parts out)
class Serial : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariantList model_data READ model_data NOTIFY modelDataChanged)
public:
explicit Serial(QObject *parent = nullptr);
QVariantList model_data() const { return model_data_; }
signals:
void modelDataChanged();
private slots:
void readSerial();
private:
QVariantList model_data_;
};
The readSerial()
function would look like this:
void Serial::readSerial()
{
QByteArray serialData = QByteArray(17 * 17 * 8, 0); //shortcut for testing
double *arr = reinterpret_cast<double*>(serialData.data());
model_data_.clear();
for(int i=0;i<17*17;i++)
{
model_data_.append(arr[i]);
}
emit modelDataChanged();
}
What happens is that the QVariant list is filled with the doubles, which have been reinterpreted from byte to doubles. Note that this has to be done every time the serialData
changes.
However, this might not be ideal in case you want to go any further with this. When changing dimensions, this setup will fail, both on arduino sending side, arduino reading side and on qml side. You should consider sending the dimensions of the array, reading those back and acting on it. One idea might be QAbstractListModel, which already has the notion of rows/columns; another, simpler idea might be to add properties to the Serial
class stating the dimensions (which where read in readSerial()
)