Qt Quick之ListView下拉刷新数据

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. class DynamicListModelPrivate;
  5. class DynamicListModel : public QAbstractListModel
  6. {
  7. Q_OBJECT
  8. Q_PROPERTY(int pageSize READ pageSize WRITE setPageSize NOTIFY pageSizeChanged)
  9. Q_PROPERTY(int total READ total WRITE setTotal NOTIFY totalChanged)
  10. public:
  11. DynamicListModel(QObject *parent = 0);
  12. ~DynamicListModel();
  13. int rowCount(const QModelIndex &parent) const;
  14. QVariant data(const QModelIndex &index, int role) const;
  15. QHash<int, QByteArray> roleNames() const;
  16. Q_INVOKABLE void loadMore(bool forward);
  17. int pageSize();
  18. void setPageSize(int size);
  19. int total();
  20. void setTotal(int total);
  21. signals:
  22. void pageSizeChanged(int size);
  23. void totalChanged(int total);
  24. private:
  25. DynamicListModelPrivate *m_dptr;
  26. };
  27. #endif // DYNAMICMODEL_H

dynamicModel.cpp:

[cpp] view plaincopy

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

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. int main(int argc, char *argv[])
  6. {
  7. QGuiApplication app(argc, argv);
  8. QQmlApplicationEngine engine;
  9. QQmlContext *ctx = engine.rootContext();
  10. ctx->setContextProperty("dynamicModel", new DynamicListModel());
  11. engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
  12. return app.exec();
  13. }

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

定义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

好啦,解说完毕。

回顾本系列文章:

时间: 2024-10-15 16:04:36

Qt Quick之ListView下拉刷新数据的相关文章

Qt qml listview 下拉刷新上拉分页控件

Qt qml listview下拉刷新和上拉分页主要根据contentY来判断.但要加上顶部下拉指示器.滚动条,并封装成可简单调用的组件,着实花了我不少精力:) [先看效果]    [功能] 1 下拉刷新和上拉分页逻辑 2 /下拉刷新 3 /上拉更多 4 /滚动栏 5 /工具栏半拉显隐 6 Author: surfsky.cnblogs.com 7 Lisence: MIT 请保留此文档声明 8 History: 9 init. surfsky.cnblogs.com, 2015-01 10 a

Android—自定义控件实现ListView下拉刷新

这篇博客为大家介绍一个android常见的功能——ListView下拉刷新(参考自他人博客,网址忘记了,阅读他的代码自己理解注释的,希望能帮助到大家): 首先下拉未松手时候手机显示这样的界面: 下面的代码是自定的扎样的控件: package com.dhsr.smartID.view; import android.content.Context; import android.util.AttributeSet; import android.view.Gravity; import andr

Android ListView 下拉刷新 点击加载更多

最近项目中用到了ListView的下拉刷新的功能,总结了一下前辈们的代码,单独抽取出来写了一个demo作为示例. 效果图 下拉刷新: 加载更多: CustomListView.java [java] view plaincopy package com.example.uitest.view; import java.util.Date; import com.example.uitest.R; import android.content.Context; import android.uti

基于Android的计步器(Pedometer)的讲解(六)——ListView下拉刷新页面

计步器(Pedometer)整个项目的源代码,最近做了比较大的修改,可能以前下载的不能运行,感兴趣的朋友可以下载来看看(记得帮小弟在github打个星~) https://github.com/296777513/pedometer 今天实现实现的下拉刷新的功能,先上几张效果图: 如图所示,今天就是要实现的这个效果 首先,分析ListView下拉刷新实现方式 1.需要添加顶部下拉加载页面 2.需要监听onScrollListener来判断当前是否显示在listview的最顶部 3.因为顶部下拉加

ListView下拉刷新、上拉载入更多之封装改进

在Android中ListView下拉刷新.上拉载入更多示例一文中,Maxwin兄给出的控件比较强大,前面有详细介绍,但是有个不足就是,里面使用了一些资源文件,包括图片,String,layout,这样不利于封装打包,下面我将源码进行改进,所有布局全部用代码实现,这样直接将src和assets打包成jar就成了一个非常方便以后使用的扩展ListView控件,代码如下: XListView: /** * @file XListView.java * @package me.maxwin.view

Android自定义ListView下拉刷新

实现的目标是本地有数据并没有刷新.下拉数据及时刷新数据. 我在网上找了某位写的MyListView,这个东西的下拉核心部分还是没有弄明白.非常感谢这位作者. XML布局文件源代码: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layou

十分钟实现ListView下拉刷新上滑加载更多

说到ListView下拉刷新几乎每个APP都会用到,所以ListView下拉刷新是很重要的,就像ListView优化一样是你必会的东西. ListView实现下拉刷新如果我们开发人员自己编写相对来说比较费事的,当我们使用第三方库之后我们再来开发这个功能就会省事很多.相比与自己实现可以少编写不少代码,Android-PullToRefresh库可以轻松实现ListView的下拉刷新功能. 要使用Android—PullToRefesh库对ListView实现下拉刷新要经过以下几个步骤: 1.下载A

ListView下拉刷新模仿微信眼睛

ListView下拉刷新模仿微信眼睛 下载地址:http://www.devstore.cn/code/info/747.html 运行截图:

listview 下拉刷新加载数据

点击头条,头条会变成以下: 然后,过一段时间,刷新完成以后,listview又setSelection(1),增加一条数据,同时,把顶部给遮挡住: 这是点击刷新,然后是下拉刷新: 最后结果和点击刷新相同.那现在开始看下代码: 首先看下所用到的控件和变量: // 状态 private static final int TAP_TO_REFRESH = 1;//点击刷新 private static final int PULL_TO_REFRESH = 2;  //拉动刷新 private sta