Qt Quick之ListView下拉刷新數據

Qt Quick裏的ListView,自己是Flickable的派生類,當你用鼠標拖曳或者手指觸摸(觸摸屏)時,會產生flickStarted和flickEnded兩個信號,利用這兩個信號,就能夠實現下拉刷新數據,固然上拉刷新也是能夠的。javascript

    建立一個Qt Quick App項目,添加dynamicModel.h和dynamicModel.cpp兩個文件,用於實現DynamicListModel。項目建立過程參考《Qt Quick 之 Hello World 圖文詳解》。java

    咱們實現的下拉刷新效果有點兒特別,每次刷新後,只保留預約義的一頁數據,好比代碼中默認的頁大小爲20。編程

    版權全部foruok,轉載請註明出處:http://blog.csdn.net/foruokapp

C++ model實現

    很簡單,直接上代碼了。函數

    dynamic.h:佈局

[cpp] view plaincopyui

  1. #ifndef DYNAMICMODEL_H  this

  2. #define DYNAMICMODEL_H  spa

  3. #include <QAbstractListModel>  .net

  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

    好啦,解說完畢。

    回顧本系列文章:

相關文章
相關標籤/搜索