首页 > 解决方案 > 使用 QSortFilterProxyModel

问题描述

请查看以下代码:

CMyModel* myModel = new CMyModel();    //This is my main model sub-classing QAbstractListItemModel
CMySortModel* mySortModel = new CMySortModel(); //This is my sort filter proxy model sub-classing QSortFilterProxyModel
mySortModel->setSourceModel(myModel);
mySortModel->setDynamicSortFilter(true);
mySortModel->setSortRole(CMyModel::displayRole);

myModel->Initialize();   // This is working fine

mySortModel->sort(0);

// myModel->Initialize();   // This is not working

当数据结构(基本上是链接到CMyModel的整数的 QList )在调用mySortModel->sort(0)之前初始化时,上面的代码工作正常。
如果在 sort 方法调用之后初始化列表,则视图基本上不显示任何数据。
然后我尝试了以下

mySortModel->sort(0);
myModel->Initialize();
mySortModel->Invalidate(); // This is working fine.

但是意识到,每次 QList 中有更新时,我都需要调用mySortModel->Invalidate()来更新我的视图。否则视图不会更新。这导致完整的视图更新,进而在我的屏幕上闪烁。
由于对 Qt/QML 模型视图编码的想法不多,所以有点卡住了这个问题。
请纠正我,如果我做错了什么。
我的模型.cpp

#include "MyModel.h"
#include <QDateTime>

CMyModel::CMyModel(QObject *parent)
  : QAbstractListModel(parent)
{
    m_mapRoles.insert(rolesEnum::displayRole, "displayRole");
}

void CMyModel::Initialize()
{
  qsrand(QDateTime::currentMSecsSinceEpoch() / 1000);
  quint32 index = 0;
  while (index < 200)
  {
    m_lstOfInts.append(qrand() % 1000);
    index++;
  }
}

int CMyModel::rowCount(const QModelIndex &parent) const
{
  Q_UNUSED(parent)
  return m_lstOfInts.count();
}

int CMyModel::columnCount(const QModelIndex &parent) const
{
  Q_UNUSED(parent)
  return 1;
}

QVariant CMyModel::data(const QModelIndex &index, int role) const
{
  Q_UNUSED(role)
  int rowVal = index.row();
  if (role == rolesEnum::displayRole)
  {
    if (rowVal >= 0 && rowVal < m_lstOfInts.count())
    {
      return m_lstOfInts.at(rowVal);
    }
  }

  return QVariant();
}


QHash<int, QByteArray> CMyModel::roleNames() const
{
  return m_mapRoles;
}

我的模型.h

#ifndef MYMODEL_H
#define MYMODEL_H
#include <QAbstractListModel>
#include <QObject>
#include <QHash>


class CMyModel : public QAbstractListModel
{
  Q_OBJECT

public:
  enum rolesEnum {
    displayRole
  };
  Q_ENUM(rolesEnum)
public:
  explicit CMyModel(QObject *parent = NULL);

  // QAbstractItemModel interface
public:
  int rowCount(const QModelIndex &parent) const;
  int columnCount(const QModelIndex &parent) const;
  QVariant data(const QModelIndex &index, int role) const;
private:
  QList<int> m_lstOfInts;
  QHash<int, QByteArray> m_mapRoles;

  // QAbstractItemModel interface
public:
  QHash<int, QByteArray> roleNames() const;
  void Initialize();
};


#endif // MYMODEL_H

我的排序模型.cpp

#include "MySortModel.h"
#include "MyModel.h"

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

}


bool CMySortModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
  return sourceModel()->data(source_left, CMyModel::displayRole).toInt() < sourceModel()->data(source_right, CMyModel::displayRole).toInt();
}

MySortModel.h

#ifndef MYSORTMODEL_H
#define MYSORTMODEL_H
#include <QSortFilterProxyModel>

class CMySortModel : public QSortFilterProxyModel
{
public:
  explicit CMySortModel(QObject* parent = NULL);

  // QSortFilterProxyModel interface
protected:
  bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;
};

#endif // MYSORTMODEL_H

主文件

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QQmlContext>
#include "MyModel.h"
#include "MySortModel.h"

int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN)
  QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

  QGuiApplication app(argc, argv);

  qmlRegisterType<CMySortModel>("CMySortModel", 1, 0, "CMySortModel");

  CMyModel* myModel = new CMyModel();
  CMySortModel* mySortModel = new CMySortModel();
  mySortModel->setSourceModel(myModel);
  mySortModel->setDynamicSortFilter(true);
  mySortModel->setSortRole(CMyModel::displayRole);


  // myModel->Initialize(); // This works
  mySortModel->sort(0);

  myModel->Initialize(); // This works when followed by a invalidate call on the proxy model
  mySortModel->invalidate();

  QQmlApplicationEngine engine;
  engine.rootContext()->setContextProperty("_myModel", mySortModel);
  engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
  if (engine.rootObjects().isEmpty())
  {
    delete mySortModel;
    mySortModel = NULL;
    delete myModel;
    myModel = NULL;
    return -1;
  }


  return app.exec();
}

main.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0

Window {
    id: window
    visible: true
    width: 800
    height: 480
    title: qsTr("Hello World")

    ScrollView {
        anchors.fill: parent
        width: parent.width
        GridView {
            anchors.fill: parent
            //columns: 2
            model: _myModel
            delegate: Text {
                id: _text
                text: model.displayRole
            }
        }
    }
}

修改 Initialize 方法如下,现在可以使用

void CMyModel::Initialize()
{
  qsrand(QDateTime::currentMSecsSinceEpoch() / 1000);
  quint32 index = 0;
  while (index < 200)
  {

    beginInsertRows(QModelIndex(), m_lstOfInts.size(), m_lstOfInts.size());
    m_lstOfInts.append(qrand() % 1000);
    index++;
    endInsertRows();
  }
}

标签: qtqmlqtquick2

解决方案


推荐阅读