zoukankan      html  css  js  c++  java
  • 35.qt quick-ListView调用C++model类

    ListView中的model可以使用c++中继承自QAbstractItemModel或QAbstractListModel的自定义模型类
    所以本章主要学习如何使用C++中的继承QAbstractListModel的model类.


    1.QAbstractListModel介绍
    QAbstractListModel为模型提供了一个标准接口,它不能被直接使用,我们必须子类化实现它.
    如果你想用于树视图,则使用子类QAbstractTableModel可能更合适。

    在对QAbstractListModel进行子分类时,必须重写:

    int rowCount(const QModelIndex &parent = QModelIndex());
    //返回显示的行数
    
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole);
    //返回index单元格下的role角色数据。通过index可以获取行号和列号
    
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole);
    //返回标题role角色对应的值(需要标题数据时重写)
    // section:段号,从0开始,对于Qt::Horizontal水平标题,则是每列的标题名,对于Qt::Vertical垂直标题,则是每行的左侧标题名
    //orientation:标题类型
    //role:对应值是Qt:: ItemDataRole枚举, 对于role角色,常用的有:
    //Qt::DisplayRole :以文本方式显示数据(QString)
    //Qt::DecorationRole :将数据作为图标来装饰(QIcon,QPixmap)
    //Qt::EditRole :可编辑的数据信息显示(QString)
    //Qt::ToolTipRole :作为工具提示显示(QString)
    //Qt::StatusTipRole :作为状态栏中显示的数据(QString)
    //Qt::WhatsThisRole :作为帮助信息栏中显示的数据(QString)
    //Qt::FontRole :设置字体(QFont)
    //Qt::TextAlignmentRole :设置模型数据的文本对齐(Qt::AlignmentFlag)
    //Qt::BackgroundRole :设置模型数据的背景色(QBrush)
    //Qt::ForegroundRole : 设置模型数据的前景色,比如字体(QBrush)
    //Qt::SizeHintRole : 设置模型数据的大小
    //Qt::UserRole : 用来存储用户角色的数据,每一个单元格数据(很多)较为复杂时使用,可以通过Qt::UserRole、Qt::UserRole + 1、Qt::UserRole + 2等来设置数据
    // 使用Qt::UserRole时,我们还需要重新重写roleNames()函数,需要返回一个QHash类,表示每个Qt::UserRole+N对应的是角色叫什么名字.

    对于可编辑列表模型,您还必须提供:

    Qt::ItemFlags QAbstractListModel::flags(const QModelIndex &index) ;
    //设置每个单元格的flag,对于可编辑模型,必须重写它,添加Qt::ItemIsEditable(可编辑属性)
    //然后当我们双击时,会默认创建一个编辑组件(这是由 delegate 完成的)然后delegate会调用QAbstractTableModel ::data(index, Qt::EditRole)读取默认编辑值
    //当我们编辑完成后, delegate会调用QAbstractTableModel :: setData (index, value, Qt::EditRole)告诉我们是否保存数据.
    
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
    //将index单元格下的role角色设置为value
    //对于可编辑模型,必须重写该函数,然后还需要重写flags()
    //返回值为true:表示设置成功,然后还需要显式发射dataChanged信号

    如果对于可调整行的模型,可以重写insertRows()、removeRows()、在实现这些函数时,还需要调用合适的父类函数,用来通知model调整了哪些内容:

    insertRows():
    //在向数据结构插入新行之前需要调用父类的beginInsertRows(),并且必须在之后立即调用endInsertRows()。
    
    RemoveRows():
    //在删除行之前需要调用父类的beginRemoveRows(),并且必须在之后立即调用endRemoveRows()。

    注意:如果要重新刷新model数据,则必须在刷新model之前调用beginResetModel(),然后刷新之后调用endResetModel。
    或者在刷新之后,emit dataChanged(index(0,0),index(rowCount,columnCount))来进行刷新视图

    • 如果想要实现QML调用C++中的某个角色的值,那么我们必须重写roleNames()函数.
    • 然后当我们在QML中获取某个角色的值时,会自动通过roleNames()函数返回的QHash类转换成一个Qt::UserRole+N.
    • 然后model会自动调用data(const QModelIndex &index, Qt::UserRole+N)来获取值返回给QML

    2.C++头文件如下所示

    #ifndef CUSTOMMODEL_H
    #define CUSTOMMODEL_H
    
    #include <QAbstractListModel>
    
    // model中的数据
    class CustomModelPrivate
    {
    public:
    CustomModelPrivate();
    void clear();
    void update();
    
    QList<QVector<QString> * > m_data;
    QHash<int, QByteArray> m_role; // 每个m_data[i]中的用户角色
    int m_rowCnt;
    };
    
    class CustomModel : public QAbstractListModel
    {
    Q_OBJECT
    public:
    explicit CustomModel(QAbstractListModel *parent = nullptr);
    int rowCount(const QModelIndex &parent) const;
    QVariant data(const QModelIndex &index, int role) const;
    QHash<int, QByteArray> roleNames() const;
    signals:
    
     
    
    private:
    CustomModelPrivate *m_dataPtr;
    };
    
    #endif // CUSTOMMODEL_H

    3.C++源文件如下所示

    #include "custommodel.h"
    #include <QDateTime>
    #include <QDebug>
    
    CustomModelPrivate::CustomModelPrivate()
    {
       m_role.insert(Qt::UserRole+0, "number");   // 第1个角色名
       m_role.insert(Qt::UserRole+1, "dev");      // 第2个角色名
       m_role.insert(Qt::UserRole+2, "status");   // 第3个角色名
       m_role.insert(Qt::UserRole+3, "date");     // 第4个角色名
       m_rowCnt =10;
       update();
    }
    
    void CustomModelPrivate::clear()
    {
        int count = m_data.size();
        if(count > 0)
        {
            for(int i = 0; i < count; i++)
            {
                delete m_data.at(i);
            }
            m_data.clear();
        }
    }
    
    void CustomModelPrivate::update()
    {
        for (int i = 0; i < m_rowCnt; i++) {
            QVector<QString>* line = new QVector<QString>(5);   // 每行model中创建5条用户数据
            line->replace(0,QString("%1").arg(i+1));
            line->replace(1,"显示器");
            line->replace(2,qrand()%2 == 0 ? "显示" : "未显示");
            line->replace(3,QDateTime::currentDateTime().addDays(-10).toString("hh:mm:ss"));
            m_data.append(line);
        }
    
    }
    
    
    CustomModel::CustomModel(QAbstractListModel *parent) : QAbstractListModel(parent)
    {
        m_dataPtr = new CustomModelPrivate();
    
    }
    
    QVariant CustomModel::data(const QModelIndex &index, int role) const
    {
        if (role >= Qt::UserRole) {              //显示内容
            return m_dataPtr->m_data[index.row()]->at(role - Qt::UserRole);
        }
    
        return QVariant();
    }
    int CustomModel::rowCount(const QModelIndex &parent) const
    {
        Q_UNUSED(parent)        //由于parent未使用,所以通过Q_UNUSED去掉编译警告
        return m_dataPtr->m_rowCnt;
    }
    
    QHash<int, QByteArray> CustomModel::roleNames() const
    {
        return m_dataPtr->m_role;
    }

    然后在main.cpp中注册类:

    qmlRegisterType<CustomModel>("Model",1,0,"CustomModel");

    4.最后main.qml如下所示

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Controls 2.5
    import Model 1.0
    Window {
        id: wind
        visible: true
         500
        height: 400
    
    
        Component {
            id: fruitDelegate
            Rectangle {
                id: rect
                border. 0.5
                border.color: "#666"
                color:  rect.ListView.isCurrentItem ? "#AACCCCCC" : "transparent"
                 wind.width
                height: 100
                Column {
                    spacing: 4
                    anchors.verticalCenter: parent.verticalCenter
                    leftPadding: 20
                    Text {
                        text: dev + number
                        font.pixelSize: 15
                        font.family: "Microsoft Yahei"
                        color: "#1F8ABF"
                    }
                    Text {
                        text: "状态: "+ status
                        font.pixelSize: 15
                        font.family: "Microsoft Yahei"
                        color: status.indexOf("未显示") >=0 ? "#FF5A47" : "#1F8ABF"
                    }
                    Text {
                        text: "时间: "+ date
                        font.pixelSize: 15
                        font.family: "Microsoft Yahei"
                        color: "#1F8ABF"
                    }
                }
                MouseArea {
                   anchors.fill: parent
                   onClicked: rect.ListView.view.currentIndex = index
                }
            }
        }
    
        ListView {
            anchors.fill: parent
            model: CustomModel { id : model }
            delegate: fruitDelegate
            focus: true
        }
    }

    效果如下所示:

     

     

     

     


    人间有真情,人间有真爱。

    如果您喜欢这里,感觉对你有帮助,并且有多余的软妹币的话,不妨投个食吧,赞赏的时候,留下美句和你的博客地址哦~   戳这里看谁投食了


查看全文
  • 相关阅读:
    linux 磁盘管理学习笔记
    Apache的Order Allow Deny心得
    NodeJs 笔记
    JavaScript 笔记
    MySQL 学习笔记
    HTML 转义符
    UTF-8 BOM(EF BB BF)
    [ Python
    [ Python
    [ Python
  • 原文地址:https://www.cnblogs.com/lifexy/p/14961397.html
  • Copyright © 2011-2022 走看看