【问题标题】:Filter model items in tree view在树视图中过滤模型项
【发布时间】:2020-03-03 12:55:05
【问题描述】:

我有一个模型类:

class ItemModel : public QAbstractItemModel
{
    Q_OBJECT
public:
    enum ItemRoles {
        ItemRole = Qt::UserRole + 1,
        NameRole,
        IdRole,
        FilterRole // To be used in filtering
    };

    QVariant data(const QModelIndex &index, int role) const;

}

模型根据角色返回数据:

QVariant ItemModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    Item *item = itemFromIndex(index);

    switch (role) {
    case ItemRole:
        return QVariant::fromValue(item);
    case NameRole:
        return QVariant::fromValue(item->entity()->objectName());
    case IdRole:
        return QVariant::fromValue(item->entity()->id().id());
    case FilterRole:
    {
        switch (item->itemTask()) {
        case Item::ItemTask::ToBeFiltered:
            return QVariant::fromValue(QString("yes"));
        default:
            return QVariant::fromValue(QString("no"));
        }
    }
    default:
        return QVariant();
    }

}

我使用了QSortFilterProxyModel 成员作为父类来过滤我的模型:

class ParentClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(ItemModel             * sceneModel      READ sceneModel      CONSTANT)
    Q_PROPERTY(QSortFilterProxyModel * sceneModelProxy READ sceneModelProxy CONSTANT)

private:
    ItemModel             *m_sceneModel;
    QSortFilterProxyModel *m_sceneModelProxy;

}

QSortFilterProxyModel在父类构造函数中设置:

ParentClass::ParentClass(QObject *parent)
    : QObject(parent)
    , m_sceneModel(new ItemModel(this))
    , m_sceneModelProxy(new QSortFilterProxyModel())
{
    // Proxy to filter out unwanted items from tree-view of model
    // Looks into a specific role for each item,
    // if data value returned for that role passes the regexp, then include item in proxy model
    m_sceneModelProxy->setFilterRole(ItemModel::ItemRoles::FilterRole);
    m_sceneModelProxy->setFilterRegExp("^no$");
    m_sceneModelProxy->setSourceModel(m_sceneModel);
}

父类注册为QML类型,在QML上使用:

ParentClass {
    id: parentClass
}

现在在 QML 上,我使用 TreeView 类型来显示模型:

TreeView {
    model: parentClass.sceneModel
    selection: ItemSelectionModel {
        model: parentClass.sceneModel
    }
    style: TreeViewStyle { // ... }
    itemDelegate: FocusScope { // ... }
    TableViewColumn { role: "name" }
}

TreeView 内部有相当多的逻辑,它依赖于parentClass.sceneModel。我用parentClass.sceneModelProxy替换了所有parentClass.sceneModel实例。

没有任何代理的原始树视图工作正常:

应用代理后,树视图为空:

我花了一些时间来调试QSortFilterProxyModel 的用法。谁能给个提示?

【问题讨论】:

  • 父元素是否通过了过滤器?另请参阅 QSFPM 的 recursiveFilteringEnabled
  • 一般来说:过滤元素的字符串和正则表达式?呃!使用布尔属性和 filterAcceptsRow 或类似...
  • @peppe 谢谢!我试过setRecursiveFilteringEnabled(true),但问题仍然存在。

标签: c++ qt qml qtreeview qabstractitemmodel


【解决方案1】:

尝试设置m_sceneModelProxy->setDynamicSortFilter(true) 或在设置后调用m_sceneModelProxy->invalidate() 一次。

【讨论】:

  • 我将其设置为true,但问题仍然存在。看起来dynamicSortFilter 属性默认设置为true
  • 另外m_sceneModelProxy->invalidate(); 也没有解决问题=(
  • 那么我假设你的模型有问题,也许你应该提供一个stackoverflow.com/help/minimal-reproducible-example。 item->itemTask() 是否返回在 switch() 语句中处理的有效值?您收到任何错误消息吗?
  • 谢谢 =) 我将提供一个最小的示例。由于模型很大,可能需要一些时间。
  • 另一件事:setFilterRegExp() 保留与表达式匹配的项目。对于 FilterRole,您希望看到的项目是否返回“否”?
【解决方案2】:

在运行应用程序时查看 Qt Creator 日志,我无意中注意到了这个日志:

QMetaProperty::read: 无法处理属性“ParentClass_QML_193::sceneModelProxy”的未注册数据类型“QSortFilterProxyModel*”

我通过注册QSortFilterProxyModel*指针的a suggested approach解析了上面的日志:

#include <QSortFilterProxyModel>

qRegisterMetaType<QSortFilterProxyModel*>("QSortFilterProxyModel*");

现在 QML TreeView 可以正确过滤掉不需要的项目 =)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-24
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-18
    相关资源
    最近更新 更多