C++传递数据到QML-setContextProperty

一、适用情况

在C++里将数据生成,然后将这个数据设置为qml的上下文属性,在qml里就能使用了

二、传递基础类型

1、main.cpp

QQuickWidget *m_widget = new QQuickWidget(this);
m_widget->setGeometry(0, 0, this->width(), this->height());
//关键代码
QString str = "zhuxy";
m_widget->rootContext()->setContextProperty("Zhuxy",str);
m_widget->setSource(QUrl("./main.qml"));
m_widget->show();

2、main.qml

import QtQuick 2.0
Rectangle
{
    id: mainWindow
    x: 30; y: 80;  1000; height: 800;
    Component.onCompleted: {
        console.log(Zhuxy);
    }
}

这里直接能用Zhuxy这个上下文属性

三、ListView+QStringList作为model

1、main.cpp

QStringList list;
list << "1" << "2";
m_widget->rootContext()->setContextProperty("Zhuxy",QVariant::fromValue(list));//不能是Test??
m_widget->setSource(QUrl("./test.qml"));
m_widget->show();

2、test.qml

import QtQuick 2.0
ListView {
100; height: 100 model: myModel delegate: Rectangle { height: 25 100 Text { text: modelData } } }

注意:经过测试这个上下文属性不能取名为Test(可能已经是内置上下文属性)

四、ListView+qml可访问的C++类

1、

mydata.h

#ifndef MYDATA_H
#define MYDATA_H

#include <QObject>

class Mydata : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString value READ value WRITE setValue NOTIFY valueChanged)
    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
  public:
    Mydata(QObject *parent = nullptr);
    Mydata(const QString &value, const QString &name, QObject *parent = nullptr);
    QString value()const;
    void setValue(const QString &value);
    QString name()const;
    void setName(const QString& name);
  signals:
    void valueChanged();
    void nameChanged();
  private:
    QString m_value;
    QString m_name;
};

#endif // MYDATA_H

value和name就是qml可访问的值

mydata.cpp

#include "mydata.h"

Mydata::Mydata(QObject *parent) : QObject(parent)
{

}

Mydata::Mydata(const QString &value, const QString &name, QObject *parent)
    : QObject(parent),m_value(value),m_name(name)
{

}

QString Mydata::value() const
{
    return m_value;
}

void Mydata::setValue(const QString &value)
{
    if(this->m_value != value) {
        this->m_value = value;
        emit valueChanged();
    }

}

QString Mydata::name() const
{
    return m_name;
}

void Mydata::setName(const QString &name)
{
    if(this->m_name != name) {
        this->m_name = name;
        emit nameChanged();
    }
}

2、test.qml

import QtQuick 2.0

Rectangle
{
    id: mainWindow
    x: 30; y: 80;  1000; height: 800;
    ListView {
        anchors.fill: parent;
        model: ParaListModel;
        delegate: delegate_list
        spacing: 20;
        orientation: ListView.Horizontal

        //委托
        Component {
            id: delegate_list;
            Rectangle {
                id: rect;
                 80;
                height: width;
                color: "green";
                Text {
                    id: text1;
                    text: value;
                    horizontalAlignment: Text.AlignHCenter;
                    verticalAlignment: Text.AlignVCenter;
                    font.pixelSize: 16;
                    anchors.horizontalCenter: parent.horizontalCenter;
                    anchors.top: parent.top;
                    anchors.topMargin: 10;
                    color: "white";
                }
                Text {
                    id: text2;
                    text: name;
                    horizontalAlignment: Text.AlignHCenter;
                    verticalAlignment: Text.AlignVCenter;
                    font.pixelSize: 16;
                    anchors.horizontalCenter: parent.horizontalCenter;
                    anchors.bottom: parent.bottom;
                    anchors.bottomMargin: 10;
                    color: "white";
                }
            }
        }
    }

}

3、main.cpp

QList<QObject*> datalist;
datalist.append(new Mydata("item1", "red"));
datalist.append(new Mydata("item2", "green"));
datalist.append(new Mydata("item3", "blue"));
datalist.append(new Mydata("item4", "yellow"));
m_widget->rootContext()->setContextProperty("ParaListModel",QVariant::fromValue(datalist));

注意必须是QObject指针类型才能放进list等容器里,因为QObject的赋值构造函数是delete的

五、ListView+QAbstractListModel子类

上面的几种不支持动态更新数据,现在这种方式支持动态更新数据,当时当list的个数增加或减少是不支持更新的。

1、C++模型类ParaListModel.h

#ifndef PARALISTMODEL_H
#define PARALISTMODEL_H

#include <QAbstractListModel>

struct ParaModel
{
    ParaModel()
    {
        value = "";
        nodeName = "";
        nodeType = "";
        tableName = "";
        fieldName = "";
        module = "";
        location = "";
        rectRadius = -1;
    }
    //核心属性
    QString value;
    QString nodeName;
    QString nodeType;
    QString tableName;
    QString fieldName;
    //附加属性
    QString module;
    QString location;
    int rectRadius;
};

class ParaListModel : public QAbstractListModel
{
    Q_OBJECT
public:
    ParaListModel(QObject* parent = 0);
    enum Roles//qml用来识别别名的规则
    {
        valueRole = Qt::UserRole + 1,
        nodeNameRole,
        nodeTypeRole,
        tableNameRole,
        fieldNameRole,
        moduleRole,
        locationRole,
        rectRadiusRole
    };
    void addModel(const ParaModel &deviceList);//C++设置值
    void update(int index, const ParaModel &paraModel);//C++更新
    int  rowCount(const QModelIndex &parent = QModelIndex()) const;//qml内部调用,不用多管直接重写即可
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;//qml内部调用,不用多管直接重写即可


protected:
    QHash<int, QByteArray> roleNames() const;//qml内部调用,不用多管直接重写即可

private:
    QList<ParaModel> m_data;
};

#endif // PARALISTMODEL_H

C++模型类ParaListModel.cpp

#include "paralistmodel.h"

ParaListModel::ParaListModel(QObject *parent)
    : QAbstractListModel(parent)
{

}

void ParaListModel::addModel(const ParaModel &paraModel)
{
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_data << paraModel;
    endInsertRows();
}



int ParaListModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_data.count();
}

QVariant ParaListModel::data(const QModelIndex &index, int role) const
{
    if (index.row() < 0 || index.row() >= m_data.count())
        return QVariant();

    const ParaModel &paraModel = m_data[index.row()];
    switch (role)
    {
    case valueRole:
        return paraModel.value;
        break;
    case nodeNameRole:
        return paraModel.nodeName;
        break;
    case nodeTypeRole:
        return paraModel.nodeType;
        break;
    case tableNameRole:
        return paraModel.tableName;
        break;
    case fieldNameRole:
        return paraModel.fieldName;
        break;
    case moduleRole:
        return paraModel.module;
        break;
    case locationRole:
        return paraModel.location;
        break;
    case rectRadiusRole:
        return paraModel.rectRadius;
        break;
    default:
        break;
    }
    return QVariant();
}

void ParaListModel::update(int index, const ParaModel &paraModel)
{
    if (index < 0 || index >= m_data.count())
        return;
    ParaModel &srcModel = m_data[index];
    if(paraModel.value != "")
    {
        srcModel.value = paraModel.value;
    }
    if(paraModel.nodeName != "")
    {
        srcModel.nodeName = paraModel.nodeName;
    }
    if(paraModel.nodeType != "")
    {
        srcModel.nodeType = paraModel.nodeType;
    }
    if(paraModel.tableName != "")
    {
        srcModel.tableName = paraModel.tableName;
    }
    if(paraModel.fieldName != "")
    {
        srcModel.fieldName = paraModel.fieldName;
    }
    if(paraModel.module != "")
    {
        srcModel.module = paraModel.module;
    }
    if(paraModel.location != "")
    {
        srcModel.location = paraModel.location;
    }
    if(paraModel.rectRadius != -1)
    {
        srcModel.rectRadius = paraModel.rectRadius;
    }
}

//qml通过这里的QByteArray来访问数据
QHash<int, QByteArray> ParaListModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[valueRole] = "value";
    roles[nodeNameRole] = "nodeName";
    roles[nodeTypeRole] = "nodeType";
    roles[tableNameRole] = "tableName";
    roles[fieldNameRole] = "fieldName";
    roles[moduleRole] = "module";
    roles[locationRole] = "location";
    roles[rectRadiusRole] = "rectRadius";
    return roles;
}

qml通过3个重写的函数来获取每个model的值:

首先通过rouCount获取model个数;

再通过roleNames获取每个变量名和其role的值;

最后根据role的值访问data函数,获取到真实值

2、test.qml

import QtQuick 2.0

Rectangle {
     800;
    height: 300;
    color: "#222648";//背景色
    property int rect_ 80;//参数宽度
    property color text_color: "white";//字体颜色
    ListView {
         parent.width;
        height: rect_width;
        anchors.centerIn: parent;
        model: ParaListModel;
        delegate: delegate_list
        spacing: 20;
        orientation: ListView.Horizontal
    }
    //委托
    Component {
        id: delegate_list;
        Rectangle {
            id: rect;
             rect_width;
            height: width;
            radius: rectRadius;
            color: bkColor;
            property string q_tableName: tableName;//其他不用显示的属性
            property string q_fieldName: fieldName;
            Text {
                id: text1;
                text: value;
                horizontalAlignment: Text.AlignHCenter;
                verticalAlignment: Text.AlignVCenter;
                font.pixelSize: 16;
                anchors.horizontalCenter: parent.horizontalCenter;
                anchors.top: parent.top;
                anchors.topMargin: 10;
                color: text_color;
            }
            Text {
                id: text2;
                text: nodeName;
                horizontalAlignment: Text.AlignHCenter;
                verticalAlignment: Text.AlignVCenter;
                font.pixelSize: 16;
                anchors.horizontalCenter: parent.horizontalCenter;
                anchors.bottom: parent.bottom;
                anchors.bottomMargin: 10;
                color: text_color;
            }
            MouseArea {
                anchors.fill: parent;
                hoverEnabled: true;
                cursorShape: (containsMouse? (pressed? Qt.ClosedHandCursor: Qt.OpenHandCursor): Qt.ArrowCursor);//设置鼠标样式
                onDoubleClicked: {
                    console.log(q_tableName,q_fieldName);
                }
            }
        }
    }

}

3、main.cpp

m_widget = new QQuickWidget(this);
m_widget->setGeometry(0, 0, this->width(), this->height());
//关键代码
ParaListModel modelList;
for(int i=0;i<5;i++)
{
    ParaModel model;
    model.value = "value:"+QString::number(i);
    model.nodeName = "nodeName:"+QString::number(i);
    model.nodeType = "nodeType:"+QString::number(i);
    model.tableName = "tableName:"+QString::number(i);
    model.fieldName = "fieldName:"+QString::number(i);
    model.rectRadius = 40;
    modelList.addModel(model);
}
m_widget->rootContext()->setContextProperty("ParaListModel",&modelList);

//测试实时更新qml中的值
ParaModel model;
model.value = "new";
model.nodeName = "new";
model.rectRadius = 10;
modelList.update(4,model);

原文地址:https://www.cnblogs.com/judes/p/13460913.html