在前端开发中,我们经常要实现分页内容,这里介绍如何通过QSortFilterProxyModel + Qml Listview实现分页。

思路

- QSortFilterProxyModel详细内容可以看Qt文档,这里主要介绍我们继承这个类要实现的部分。我们继承这个类通过实现抽象函数filterAcceptsRow来实现单个页面的内容过滤。
给qml暴露下面属性
- pageSize
- pageIndex
- count
PageModelSorter.h
#include <QSortFilterProxyModel>
class PageModelSorter: public QSortFilterProxyModel{
Q_OBJECT
Q_PROPERTY(int pageIndex READ pageIndex WRITE setPageIndex NOTIFY pageIndexChanged)
Q_PROPERTY(int pageSize READ pageSize WRITE setPageSize NOTIFY pageSizeChanged)
Q_PROPERTY(int count READ count NOTIFY countChanged)
public:
PageModelSorter(QObject* parent);
~PageModelSorter();
int pageIndex() const;
void setPageIndex(int pageIndex);
int pageSize() const;
void setPageSize(int pageSize);
int count() const;
signals:
void pageIndexChanged(const int& pageIndex);
void pageSizeChanged(const int& pageSize);
void countChanged(const int& count);
protected:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;
private:
int m_pageIndex;
int m_pageSize;
};
PageModelSorter.cpp
#include "modelsorter.h"
PageModelSorter::PageModelSorter(QObject *parent):
QSortFilterProxyModel (parent)
{
emit countChanged(rowCount());
}
PageModelSorter::~PageModelSorter()
{
}
bool PageModelSorter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
Q_UNUSED(source_parent);
int min = m_pageSize * m_pageIndex;
int max = m_pageSize * m_pageIndex + m_pageSize;
return source_row >= min && source_row < max;
}
bool PageModelSorter::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
return QSortFilterProxyModel::lessThan(source_left, source_right);
}
int PageModelSorter::pageSize() const
{
return m_pageSize;
}
void PageModelSorter::setPageSize(int pageSize)
{
m_pageSize = pageSize;
emit pageSizeChanged(pageSize);
emit layoutChanged();
}
int PageModelSorter::count() const
{
return rowCount();
}
int PageModelSorter::pageIndex() const
{
return m_pageIndex;
}
void PageModelSorter::setPageIndex(int pageIndex)
{
m_pageIndex = pageIndex;
emit pageIndexChanged(pageIndex);
emit layoutChanged();
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "pagemodel.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterType<PageModelSorter>("PageModel", 1, 0, "PageModel");
auto builder = new ModelBuilder<ISong, SongOperate>(&lDatas);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
- qml端实现
PageDelegate.qml
import QtQuick 2.0
import PageModel 1.0
Rectangle{
property int pageNo;
property QtObject source;
property int sizeInPage;
id: page
Grid{
anchors.centerIn: parent
spacing: 10
columns: 5
Repeater{
model: PageModel{
sourceModel: source
pageIndex: pageNo
pageSize: sizeInPage
}
delegate: SongDelegate{}
}
}
}
SongDelegate.qml
import QtQuick 2.0
Rectangle{
width: 200
height: 100
border.width: 1
border.color: "#7799aa"
color: "#aaeeff"
radius: 4
Column{
anchors.centerIn: parent
spacing: 10
Text{
text: "歌名: " + SongName
}
Text{
text: "歌手: " + SingerName
}
Text{
text: "歌号: " + SongNo
}
}
}
SongPage.qml
import QtQuick 2.0
import QtQuick.Controls 2.5
import "./Delegates"
Item {
property int pageSize: 20
property int pageCount: songModel.rowCount() % pageSize === 0 ? songModel.rowCount() / pageSize : Math.round(songModel.rowCount() / pageSize) + 1
Column{
anchors.fill: parent
ListView{
id:listView
orientation: ListView.Horizontal
width: parent.width
height: parent.height - 60
model: pageCount
highlightRangeMode : ListView.StrictlyEnforceRange
highlightMoveDuration: 200
highlightMoveVelocity: -1
snapMode: ListView.SnapOneItem
delegate: PageDelegate{
pageNo: index
source: songModel
sizeInPage: pageSize
width: listView.width
height: listView.height
}
}
Item{
width: parent.width
height: 60
Row{
anchors.centerIn: parent
spacing: 20
Button{
text: "Previous"
width: 70
height: 40
onClicked: {
if(listView.currentIndex > 0)
listView.currentIndex -= 1
}
}
Text{
text: String(listView.currentIndex + 1) + "/" + String(pageCount)
anchors.verticalCenter: parent.verticalCenter
}
Button{
text: "Next"
width: 70
height: 40
onClicked: {
if(listView.currentIndex < pageCount - 1)
listView.currentIndex += 1
}
}
}
}
}
}
main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
width: 1300
height: 600
minimumHeight: 600
minimumWidth: 1200
title: qsTr("Hello World")
SongPage{
anchors.fill: parent
}
}
网友评论