栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

QML使用C++model(排序/搜索)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

QML使用C++model(排序/搜索)

上一篇介绍介绍了C++model的基本用法,只实现了增删改,实际项目开发中,还有很常见的功能就是排序和查询。Qt提供了QSortFilterProxyModel实现排序和查询的功能。

排序查询

QSortFilterProxyModel,顾名思义,排序过滤代理model,搜索查询本质上就是过滤。至于代理,就是QSortFilterProxyModel只是原model的代理,原始数据还是在原model上,代理model根据相应的规则存储进行处理后的数据,源数据在源model是不变的。比如芒果的代理商,实际上果农果园里有很多品种的芒果,但市场上主流的两三种,代理商售卖就只卖这两三种,果农就是原model,代理商就是QSortFilterProxyModel。

QSortFilterProxyModel提供了以下接口绑定model

void setSourceModel(QAbstractItemModel *sourceModel) override
排序

sort接口实现排序,第二个参数是选择升序还是降序

void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override

对于我们自定义的model来说,需要选择要排序的role类型,一般搭配setSortRole使用

void setSortRole(int role);

对于自定义的类型,需要自定义自己的排序规则,可重载

bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
bool MySortFilterProxyModel::lessThan(const QModelIndex &left,
                                      const QModelIndex &right) const
{
    QVariant leftData = sourceModel()->data(left);
    QVariant rightData = sourceModel()->data(right);
//! [4]

//! [6]
    if (leftData.userType() == QMetaType::QDateTime) {
        return leftData.toDateTime() < rightData.toDateTime();
    } else {
        static const QRegularExpression emailPattern("[\w\.]*@[\w\.]*");

        QString leftString = leftData.toString();
        if (left.column() == 1) {
            const QRegularExpressionMatch match = emailPattern.match(leftString);
            if (match.hasMatch())
                leftString = match.captured(0);
        }
        QString rightString = rightData.toString();
        if (right.column() == 1) {
            const QRegularExpressionMatch match = emailPattern.match(rightString);
            if (match.hasMatch())
                rightString = match.captured(0);
        }

        return QString::localeAwareCompare(leftString, rightString) < 0;
    }
}

上面的例子中只比较邮箱部分的数据

过滤

 过滤最常见的的应用就是搜索功能,就是过滤匹配关键字,使用QSortFilterProxyModel也很容易实现

重写函数

bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
bool DataListProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
    QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
    auto typeData = sourceModel()->data(index0, DataListModel::TypeRole).toString();
    auto sizeData = sourceModel()->data(index0, DataListModel::SizeRole1).toString();
    return typeData.contains(filterRegExp()) || sizeData.contains(filterRegExp());
}

里面实现想要过滤的内容,上面的例子就返回满足TypeRole和SizeRole1其中一项的数据

执行过滤是调用,参数就是过滤规则

void setFilterRegExp(const QRegExp ®Exp);

QRegExp除了关键的key值pattern外,还有Qt::CaseSensitivity支持是否区分大小写,第三个参数是其他一些匹配规则,我也很少用到

explicit QRegExp(const QString &pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive,
                     PatternSyntax syntax = RegExp);
demo展示

 以上就是基于QSortFilterProxyModel实现的排序和搜索功能,实现还是很简单的

源model和上一篇博客介绍的model是一样的,在此基础上增加一个QSortFilterProxyModel,不同的是QML显示的是QSortFilterProxyModel,就是QML显示的是处理的数据,这个应该好理解。

#include 

class DataListProxyModel : public QSortFilterProxyModel
{
    Q_OBJECT
public:
    explicit DataListProxyModel(QObject *parent = nullptr);

    Q_INVOKABLE void setFilter(const QString &text);

    Q_INVOKABLE void startSort();
protected:
    bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
//    bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
};
#include "datalistproxymodel.h"
#include "datalistmodel.h"

DataListProxyModel::DataListProxyModel(QObject *parent):
    QSortFilterProxyModel(parent)
{

}

void DataListProxyModel::setFilter(const QString &text)
{
    QRegExp regExp(text);
    this->setFilterRegExp(regExp);
}

void DataListProxyModel::startSort()
{
    setSortRole(DataListModel::TypeRole);
    sort(0, Qt::DescendingOrder);
}

bool DataListProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
    QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
    auto typeData = sourceModel()->data(index0, DataListModel::TypeRole).toString();
    auto sizeData = sourceModel()->data(index0, DataListModel::SizeRole1).toString();
    return typeData.contains(filterRegExp()) || sizeData.contains(filterRegExp());
}

主函数main

int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

    QGuiApplication app(argc, argv);

    DataListModel model;
    model.append( ModelData("wolf.jpg", "Medium") );
    model.append( ModelData("polarbear.jpg", "Large") );
    model.append( ModelData("quoll.jpg", "Small") );

    DataListProxyModel proxyModel;
    proxyModel.setSourceModel(&model);

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("myModel", &proxyModel);
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

设置setSourceModel,该例子采用C++与QML交互的另一种方式,model是在c++创建,把对象注册到QML中使用,该例子是注册对象QSortFilterProxyModel,使用代理model进行显示

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15


Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Column {
        anchors.fill: parent
        Row {
            TextField {
                id: searchInput
                width: 100
                height: 30

                onTextChanged: {
                    myModel.setFilter(text)
                }
            }

            Button {
                text: "sort"
                onClicked: {
                    myModel.startSort()
                }
            }
        }
        ListView {
            id: listview
            clip: true
            width: parent.width
            height: parent.height

            model: myModel
            delegate: Item {
                id: delegate
                width: listview.width
                height: 30
                Row {
                    spacing: 5
                    Text {
                        text: type
                    }

                    Text {
                        text: size
                        color: "red"
                    }

                    Button  {
                        height: parent.height
                        onClicked: {
                            myModel.remove(index);
                        }
                    }


                }

            }
        }
    }

结语

以上就是一个排序搜索的功能,界面布局有点挫,将就着看,重点是功能。更多例子了解可参考Qt例子

前两个例子是Widget的实现的, 但QSortFilterProxyModel的用法是一样的,第三个是QML,但使用的是QML,没有基于QSortFilterProxyModel,有需要可以看看。由于边幅的原因,基于model的撤销恢复功能留到下一篇来介绍了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/990281.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号