QML中使用C++Model

转自:https://blog.csdn.net/fxy0325/article/details/81434762
使用C++model:

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

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

代码实现:

datamodel.h

#ifndef DATAMODEL_H
#define DATAMODEL_H
 
#include <QAbstractListModel>
 
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<Data> 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)
            }
        }
    }
}

运行效果:
在这里插入图片描述
自己输入颜色的名称,点击Add即可添加成功
转自:https://blog.csdn.net/fxy0325/article/details/81434762

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值