Qt Quick之ListView下拉刷新数据

来源:互联网 发布:佐伊技能数据 编辑:程序博客网 时间:2024/05/20 23:06

Qt Quick里的ListView,本身是Flickable的派生类,当你用鼠标拖曳或者手指触摸(触摸屏)时,会产生flickStarted和flickEnded两个信号,利用这两个信号,就可以实现下拉刷新数据,当然上拉刷新也是可以的。

    创建一个Qt Quick App项目,添加dynamicModel.h和dynamicModel.cpp两个文件,用于实现DynamicListModel。项目创建过程参考《Qt Quick 之 Hello World 图文详解》。

    我们实现的下拉刷新效果有点儿特别,每次刷新后,只保留预定义的一页数据,比如代码中默认的页大小为20。

    版权所有foruok,转载请注明出处:http://blog.csdn.net/foruok。

C++ model实现

    很简单,直接上代码了。

    dynamic.h:

[cpp] view plaincopy
  1. #ifndef DYNAMICMODEL_H  
  2. #define DYNAMICMODEL_H  
  3. #include <QAbstractListModel>  
  4.   
  5. class DynamicListModelPrivate;  
  6. class DynamicListModel : public QAbstractListModel  
  7. {  
  8.     Q_OBJECT  
  9.     Q_PROPERTY(int pageSize READ pageSize WRITE setPageSize NOTIFY pageSizeChanged)  
  10.     Q_PROPERTY(int total READ total WRITE setTotal NOTIFY totalChanged)  
  11. public:  
  12.     DynamicListModel(QObject *parent = 0);  
  13.     ~DynamicListModel();  
  14.   
  15.     int rowCount(const QModelIndex &parent) const;  
  16.     QVariant data(const QModelIndex &index, int role) const;  
  17.     QHash<int, QByteArray> roleNames() const;  
  18.   
  19.     Q_INVOKABLE void loadMore(bool forward);  
  20.   
  21.     int pageSize();  
  22.     void setPageSize(int size);  
  23.     int total();  
  24.     void setTotal(int total);  
  25.   
  26. signals:  
  27.     void pageSizeChanged(int size);  
  28.     void totalChanged(int total);  
  29.   
  30. private:  
  31.     DynamicListModelPrivate *m_dptr;  
  32. };  
  33.   
  34. #endif // DYNAMICMODEL_H  

    dynamicModel.cpp:

[cpp] view plaincopy
  1. #include "dynamicModel.h"  
  2. #include <QDebug>  
  3.   
  4. class DynamicListModelPrivate  
  5. {  
  6. public:  
  7.     DynamicListModelPrivate(DynamicListModel *model)  
  8.         : m_model(model), m_start(0), m_end(20)  
  9.         , m_total(100), m_pageSize(20)  
  10.     {  
  11.         m_roleNames.insert(Qt::UserRole, "content");  
  12.     }  
  13.   
  14.     void pageDown()  
  15.     {  
  16.         if(m_end < m_total)  
  17.         {  
  18.             m_start += m_pageSize;  
  19.             m_end += m_pageSize;  
  20.             if(m_end > m_total)  
  21.             {  
  22.                 m_end = m_total;  
  23.                 m_start = m_end - m_pageSize;  
  24.             }  
  25.         }  
  26.     }  
  27.   
  28.     void pageUp()  
  29.     {  
  30.         if(m_start > 0)  
  31.         {  
  32.             m_start -= m_pageSize;  
  33.             if(m_start < 0) m_start = 0;  
  34.             m_end = m_start + m_pageSize;  
  35.         }  
  36.     }  
  37.   
  38.     void adjustPageRange()  
  39.     {  
  40.         if(m_end - m_start < m_pageSize)  
  41.         {  
  42.             m_end = m_start + m_pageSize;  
  43.             if(m_end > m_total)  
  44.             {  
  45.                 m_end = m_total;  
  46.                 m_start = m_end - m_pageSize;  
  47.             }  
  48.         }  
  49.     }  
  50.   
  51.     DynamicListModel *m_model;  
  52.     int m_start;  
  53.     int m_end;  
  54.     int m_total;  
  55.     int m_pageSize;  
  56.     QHash<int, QByteArray> m_roleNames;  
  57. };  
  58.   
  59. DynamicListModel::DynamicListModel(QObject *parent)  
  60.     : QAbstractListModel(parent),  
  61.     m_dptr(new DynamicListModelPrivate(this))  
  62. {  
  63.   
  64. }  
  65.   
  66. DynamicListModel::~DynamicListModel()  
  67. {  
  68.     delete m_dptr;  
  69. }  
  70.   
  71. int DynamicListModel::rowCount(const QModelIndex &parent) const  
  72. {  
  73.     return m_dptr->m_end - m_dptr->m_start;  
  74. }  
  75.   
  76. QVariant DynamicListModel::data(const QModelIndex &index, int role) const  
  77. {  
  78.     int row = index.row();  
  79.     //qDebug() << "index.row - " << row << " start - " << m_dptr->m_start;  
  80.     return QString::number(row + m_dptr->m_start);  
  81. }  
  82.   
  83. QHash<int, QByteArray> DynamicListModel::roleNames() const  
  84. {  
  85.     return m_dptr->m_roleNames;  
  86. }  
  87.   
  88. void DynamicListModel::loadMore(bool forward)  
  89. {  
  90.     beginResetModel();  
  91.     if(forward)m_dptr->pageDown();  
  92.     else m_dptr->pageUp();  
  93.     endResetModel();  
  94. }  
  95.   
  96. int DynamicListModel::pageSize()  
  97. {  
  98.     return m_dptr->m_pageSize;  
  99. }  
  100.   
  101. void DynamicListModel::setPageSize(int size)  
  102. {  
  103.     m_dptr->m_pageSize = size;  
  104.     m_dptr->adjustPageRange();  
  105.     emit pageSizeChanged(size);  
  106. }  
  107.   
  108. int DynamicListModel::total()  
  109. {  
  110.    return m_dptr->m_total;  
  111. }  
  112.   
  113. void DynamicListModel::setTotal(int total)  
  114. {  
  115.     m_dptr->m_total = total;  
  116.     m_dptr->adjustPageRange();  
  117.     emit totalChanged(total);  
  118. }  

    DynamicListModel仅仅是演示用法,使用m_start、m_end、m_total、m_pageSize四个整型变量来模拟实际的数据。而data()方法,将ListView内的行序号加上m_start转换为字符串返回,就是我们在ListView界面上看到了文字了。

    loadMore()函数,区分向前还是向后加载数据,它调用DynamicListModel的pageDown()、pageUp()来更新内部的数据状态。在loadMore()一开始,调用beginResetModel(),通知关联到DynamicListModel上的view们刷新自己,当内部数据状态更新结束后,调用endResetModel()来通知view们,这样view们就会刷新,最终在实例化item delegate时调用data()方法来准备数据,此时m_start已变化,所以界面上看到的数字也跟着变了。

导出C++ Model

    这个简单,我们在《Qt Quick 之 QML 与 C++ 混合编程详解》一文中已经讲过。直接看main.cpp:

[cpp] view plaincopy
  1. #include <QGuiApplication>  
  2. #include <QQmlApplicationEngine>  
  3. #include <QQmlContext>  
  4. #include "dynamicModel.h"  
  5.   
  6. int main(int argc, char *argv[])  
  7. {  
  8.     QGuiApplication app(argc, argv);  
  9.   
  10.     QQmlApplicationEngine engine;  
  11.     QQmlContext *ctx = engine.rootContext();  
  12.     ctx->setContextProperty("dynamicModel"new DynamicListModel());  
  13.     engine.load(QUrl(QStringLiteral("qrc:///main.qml")));  
  14.   
  15.     return app.exec();  
  16. }  

QML代码介绍

    是时候看看main.qml了:

[javascript] view plaincopy
  1. import QtQuick 2.2  
  2. import QtQuick.Window 2.1  
  3. import QtQuick.Controls 1.2  
  4. import QtQuick.Layouts 1.1  
  5. import QtQuick.Controls.Styles 1.2  
  6.   
  7. Window {  
  8.     width: 320;  
  9.     height: 480;  
  10.     minimumWidth: 300;  
  11.     minimumHeight: 480;  
  12.     visible: true;  
  13.     id: root;  
  14.   
  15.     Component {  
  16.         id: listDelegate;  
  17.         Text {  
  18.             id: wrapper;  
  19.             width: parent.width;  
  20.             height: 32;  
  21.             font.pointSize: 15;  
  22.             verticalAlignment: Text.AlignVCenter;  
  23.             horizontalAlignment: Text.AlignHCenter;  
  24.             text: content;  
  25.             color: ListView.view.currentIndex == index ? "red" : "blue";  
  26.             MouseArea {  
  27.                 anchors.fill: parent;  
  28.                 onClicked: {  
  29.                     if(wrapper.ListView.view.currentIndex != index){  
  30.                         wrapper.ListView.view.currentIndex = index;  
  31.                     }  
  32.                 }  
  33.             }  
  34.         }  
  35.     }  
  36.   
  37.     ListView {  
  38.         id: dynamicList;  
  39.         z: 1;  
  40.         anchors.fill: parent;  
  41.         anchors.margins: 10;  
  42.   
  43.         delegate: listDelegate;  
  44.         model: dynamicModel;  
  45.   
  46.         focus: true;  
  47.         activeFocusOnTab: true;  
  48.         highlight: Rectangle {  
  49.             color: "steelblue";  
  50.         }  
  51.   
  52.         property real contentYOnFlickStarted: 0;  
  53.         onFlickStarted: {  
  54.             //console.log("start,origY - ", originY, " contentY - ", contentY);  
  55.             contentYOnFlickStarted = contentY;  
  56.         }  
  57.   
  58.         onFlickEnded: {  
  59.             //console.log("end,origY - ", originY, " contentY - ", contentY);  
  60.             dynamicModel.loadMore(contentY < contentYOnFlickStarted);  
  61.         }  
  62.     }  
  63. }  

    定义ListView对象时,指定其model为main()函数中导出的dynamicModel,其它的代码不必细说了,咱们单看实现下拉(上拉)刷新的关键代码。

    onFlickStarted信号处理器,在这里我们仅仅是将flick开始时的contentY记录到contentYOnFlickStarted属性中。

    onFlickEnded信号处理器,这里比较flick结束时的contentY和开始时的contentY(即contentYOnFlickStarted),结束时小,说明是下拉,结束时大,说明是上拉。根据比较结果调用loadMore()。

    好啦,就这么简单了。看看效果。

下拉刷新效果

    图1是初始效果:


             图1动态刷新列表初始效果

    图2是下拉了两次后的效果:


             图2 下拉刷新后的效果

    图3是从图2所示状态上拉后的效果:


             图3 上拉后的效果


    版权所有foruok,转载请注明出处:http://blog.csdn.net/foruok。

    好啦,解说完毕。

    回顾本系列文章:

  • Qt Quick 简介
  • QML 语言基础
  • Qt Quick 之 Hello World 图文详解
  • Qt Quick 简单教程
  • Qt Quick 事件处理之信号与槽
  • Qt Quick事件处理之鼠标、键盘、定时器
  • Qt Quick 事件处理之捏拉缩放与旋转
  • Qt Quick 组件与对象动态创建详解
  • Qt Quick 布局介绍
  • Qt Quick 之 QML 与 C++ 混合编程详解
  • Qt Quick 图像处理实例之美图秀秀(附源码下载)
  • Qt Quick 之 PathView 详解
  • Qt Quick实例之挖头像
  • Qt Quick综合实例之文件查看器
0 0
原创粉丝点击