码迷,mamicode.com
首页 > 其他好文 > 详细

Qt Quick之ListView下拉刷新数据

时间:2015-06-06 10:43:25      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:

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之ListView下拉刷新数据

标签:

原文地址:http://my.oschina.net/u/574940/blog/425520

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!