c++ - 如何使用Repeater和GridView将二维数组的值从C++显示到QML
问题描述
从 C++ 在 QML 上显示二维数组 QString 的值时出现问题
我有要在 QML 上使用的数据和 qmlRegisterType。
这是 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]
}
}
}
}
}
}
这是 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();
}
串行.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
串行.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/sec。我的逻辑是:每当数据发生变化时,QML 都会显示新数据
解决方案
在您的代码中,我看到以下错误:
或者您使用 qmlRegisterType 注册类型或将其设置为 contextProperty,而不是两者。我建议您检查选择 C++ 和 QML 之间的正确集成方法。
在您的转发器中,您正在创建 N MySerial 但您只能拥有 1 个,想法是您创建一个 MySerial 并将信息传递给模型。
不要使用
QList<QString>
但是QStringList
。您的数据不应从 QML 写入,因此 modelData 属性不必为 Writeble。
考虑到上述情况并避免部分数据解码,因为我不知道将取代它的格式创建随机数据,解决方案如下:
串行.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
串行.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();
}
主文件
#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
}
}
}
}
}
推荐阅读
- javascript - Javascript Regex:匹配任何不是空白字符的非单词字符
- php - 防止没有输入的mysql查询
- kotlin - 如何有效地从 Kotlin 中的集合(Top N)中获取 N 个最低值?
- transcrypt - 如何在 transcrypt 中导入名称中带有“-”的模块?
- c# - System.InvalidOperationException: '已经有一个打开的 DataReader 与此命令关联,必须先关闭。'
- mysql - SQL 过滤与另一个表中的所有条目匹配的条目
- performance - Spring Boot 作业的执行时间
- javascript - NodeJS 和 console.log 没有记录
- react-native - React Native - 在构建时生成错误的tipsi-stripe包(无法解决依赖关系)
- android - 如何在 ViewPager 中设置固定背景