C++给qml传入一个自定义数据结构的list

我在上一篇文章已经写过三个方法用C++给qml传入自定义list,但是那三个方法都不支持数据的更新,也就是说C++这边的数据发生了改变,listview是不知道数据发生变化的。这样使用起来局限性很大,特别是一些有数据变化的场合,就没法使用了。下面介绍第四种方法,可以更新listview的数值。
整体思路是:
step1:根据自己的项目需求创建自定义数据结构
step2:创建数据模型
step3:将定义的数据模型传入qml

下面详细介绍每一步

step1创建自定义数据结构

class DeviceList {
  public:
    DeviceList(const QString &name, const QString &value, const QString unit);

    QString name() const {
        return m_name;
    }
    QString value() const {
        return m_value;
    }
    QString unit()const {
        return m_unit;
    }
  private:
    QString m_name;
    QString m_value;
    QString m_unit;
};

这里定义了一个DeviceList类,里面有 name,value,unit三个数据成员。

step2创建数据模型

数据模型必须具备两个条件:
1、必须继承QAbstractListModel这个类。目的是当数据发生变化时,能够自动的通知QML view。
2、由于会用到信号槽,所以要加入 Q_OBJECT宏

class DeviceListModel : public QAbstractListModel {
    Q_OBJECT
  public:
    enum AnimalRoles {
        nameRole = Qt::UserRole + 1,
        valueRole,
        nuitRole
    };

    DeviceListModel(QObject *parent = 0);
    //目的是添加新的设备
    void addDevice(const DeviceList &devicelist);
    //返回list节点个数
    int rowCount(const QModelIndex & parent = QModelIndex()) const;
    //返回数据
    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;

  protected:
  //Returns the model's role names.
    QHash roleNames() const;
  private:
    QList m_runTimeData;
};

DeviceListModel::DeviceListModel(QObject *parent)
    : QAbstractListModel(parent) {
}

void DeviceListModel::addDevice(const DeviceList &deviceList) {
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_runTimeData << deviceList;
    endInsertRows();
}

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

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

    const DeviceList &deviceList = m_runTimeData[index.row()];
    if (role == nameRole)
        return deviceList.name();
    else if (role == valueRole)
        return deviceList.value();
    else if (role == nuitRole)
        return deviceList.unit();
    return QVariant();
}

QHash DeviceListModel::roleNames() const {
    QHash roles;
    roles[nameRole] = "name";
    roles[valueRole] = "value";
    roles[nuitRole] = "unit";
    return roles;
}

DeviceList::DeviceList(const QString &name, const QString &value, const QString unit)
    : m_name(name), m_value(value), m_unit(unit) {

}

step3把模型传入qml

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

    QGuiApplication app(argc, argv);


    DeviceListModel model;
    model.addDevice(DeviceList("ch1局放强度", "1000", "mV"));
    model.addDevice(DeviceList("ch2局放强度", "500", "mV"));
    model.addDevice(DeviceList("ch3局放强度", "800", "mV"));
    model.addDevice(DeviceList("ch1局放能量", "10", "mW"));
    model.addDevice(DeviceList("ch2局放能量", "20", "mW"));
    model.addDevice(DeviceList("ch3局放能量", "15", "mW"));

    QQmlApplicationEngine engine;
    QQmlContext *ctxt = engine.rootContext();
    ctxt->setContextProperty("myModel", &model);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    return app.exec();
}

qml部分代码

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    visible: true
    id:page
    Row{
        id:tableTitle
        Rectangle{
            width:page.width/3
            height:tableName.font.pixelSize
            Text{
                id:tableName
                text:"测点名称"
                anchors.centerIn: parent
            }
        }
        Rectangle{
            width:page.width/3
            height:tableName.font.pixelSize
            Text{
                id:value
                text:"测量值"
                anchors.centerIn: parent
            }
        }
        Rectangle{
            width:page.width/3
            height:tableName.font.pixelSize
            Text{
                id:unit
                text:"单位"
                anchors.centerIn: parent
            }
        }
    }
    ListView{
        anchors.top: tableTitle.bottom
        width: page.width
        height: page.height-tableTitle.height
        model:myModel
        delegate: myDeleagta
        Component{
        id:myDeleagta
            Row{
                Rectangle{
                    width:page.width/3
                    height:tableName.font.pixelSize
                    Text{
                        text :name
                        anchors.centerIn: parent
                    }
                }
                Rectangle{
                    width:page.width/3
                    height:tableName.font.pixelSize
                    Text{
                        text:value
                        anchors.centerIn: parent
                    }
                }
                Rectangle{
                    width:page.width/3
                    height:tableName.font.pixelSize
                    Text{
                        text:unit
                        anchors.centerIn: parent
                    }
                }
            }
        }


    }
}

由于安卓不支持tableView,只用能listView自定义个tableView了

最后运行效果

C++给qml传入一个自定义数据结构的list_第1张图片

你可能感兴趣的:(qml,listview,c++)