QML中使用C++Model

    xiaoxiao2023-10-15  151

    使用C++model:

    当需要少量数据时,QML中直接定义模型时非常方便。

    当数据较为复杂或者想在c++里操纵数据时,可以在C++中设计Model并在qml中展示数据,这样会更加稳定可靠。

    Qt向导里可以方便地添加Model类。在新建文件里,Qt->QT Item Model。

    代码实现: datamodel.h #ifndef DATAMODEL_H #define DATAMODEL_H

    #include

    class Data { public: Data(const QString &title,const QString &color);

    QString title() const; QString color() const;

    private: QString title_; QString color_; };

    class DataModel : public QAbstractListModel { Q_OBJECT

    public: enum DataRoles{ TitleRole = Qt::UserRole + 1, ColorRole };

    explicit DataModel(QObject *parent = nullptr); ~DataModel(); // Basic functionality: int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; // Add data: Q_INVOKABLE void insert(int index,const Data &data) ; // Remove data: Q_INVOKABLE void remove(int index); Q_INVOKABLE void append(const QString &title,const QString &color); int count() const;

    protected: // interface QAbstractListModel virtual QHash<int, QByteArray> roleNames() const;

    private: QList dataList_; };

    #endif // DATAMODEL_H 这里定义了一个数据类型Data,包含了title和color两个数据项,根据自己的需求定义。也定义了我们的DataModel.这就是qml中需要使用的C++model了。

    以下两个是自定义model类必须实现的接口(因为是listmodel所以只需要实现行的rowCount) int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

    类内声名了一个枚举类型(DataRoles),每个类型对应数据项中被访问的一个属性。

    QVariant data(const QModelIndex &index, int role)是访问每个列表项的接口,访问的时候会通过index代表索引,role代表查找的属性(对应定义的枚举类型 DataRoles)。

    roleNames函数设置自己的类型,返回role的别名,提供给qml使用。

    如果qml中不需要使用的函数,则不需要声明Q_INVOKABLE 。

    datamodel.cpp #include “datamodel.h”

    Data::Data(const QString &title, const QString &color) :title_(title) ,color_(color) {

    }

    QString Data::title() const { return title_; }

    QString Data::color() const { return color_; }

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

    DataModel::~DataModel() { }

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

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

    const Data &data = dataList_[row]; switch (role) { case TitleRole: return data.title(); break; case ColorRole: return data.color(); break; } return QVariant();

    }

    //dm : data model QHash<int, QByteArray> DataModel::roleNames() const { QHash<int, QByteArray> roles; roles[TitleRole] = “dmTitle”; roles[ColorRole] = “dmColor”; return roles; // emit countChanged(m_data.count()); }

    void DataModel::insert(int index, const Data &data) { if(index < 0 || index > dataList_.count()) { return; }

    emit beginInsertRows(QModelIndex(), index, index); dataList_.insert(index, data); emit endInsertRows();

    // emit countChanged(m_data.count()); }

    void DataModel::remove(int index) { if(index < 0 || index >= dataList_.count()) { return; }

    beginRemoveRows(QModelIndex(), index, index); dataList_.removeAt(index); endRemoveRows();

    }

    void DataModel::append(const QString &title,const QString &color) { insert(count(), Data(title,color)); }

    int DataModel::count() const { return rowCount(QModelIndex()); } 在进行增删的时候必须先调用beginInsertRows(QModelIndex, int , int),其中第一个参数代表的是 Model 数据,QModelIndex()得到这个Model的虚拟rootItem;后两个参数代表所改动的行数范围,如在第三行加入2个数据(则是从第三行改动到第五行),则两个参数分别是(3,5),此处只修改一行,所以两个参数相同。修改完成后还要调用endInsertRows()声名修改完毕。必须调用beginInsertRows和endInsertRows,这样底层就能正确处理数据的变化,并且将变化及时的反应到View中。插入函数同理。

    更多信息:http://doc.qt.io/qt-5/qabstractitemmodel.html#beginInsertRows

    在main.cpp中注册到上下文 DataModel model; model.append(“orange item”,“orange”);

    QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("$Model",&model); engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    在 QML 中读取 可以看到model中定义的别名dmColor ,dmTitle在这里使用。

    import QtQuick 2.6 import QtQuick.Window 2.2 import QtQuick.Layouts 1.2 import QtQuick.Controls 1.4 Window { visible: true width: 640 height: 480 title: qsTr(“Model”)

    ListView { id: view width: parent.width height: parent.height-rect_input.height // set our dynamic model to the views model property model: $Model delegate: Rectangle { width: view.width height: 40 border.color: Qt.darker(color) // construct a string based on the models proeprties color: dmColor Text { anchors.left: parent.left text: dmTitle } Image{ id: icon anchors.right: parent.right source: "/image/remove.png" MouseArea{ anchors.fill: parent onClicked: $Model.remove(index) } } } } RowLayout { id:rect_input anchors.bottom: parent.bottom width: parent.width height: 50 TextField{ id: text_title Layout.fillWidth: true text: 'orange item' } TextField { id: text_color Layout.fillWidth: true text: 'orange' } Button { text: 'Add' onClicked: { $Model.append(text_title.text,text_color.text) } } }

    } 运行效果图

    原文:https://blog.csdn.net/fxy0325/article/details/81434762

    最新回复(0)