首页 > 其他分享 >QListView 使用QSortFilterProxyModel 过滤后的Item 无法拖动改变顺序

QListView 使用QSortFilterProxyModel 过滤后的Item 无法拖动改变顺序

时间:2024-11-24 21:00:06浏览次数:11  
标签:QListView Qt 模型 Item listView QSortFilterProxyModel QModelIndex

当使用 QSortFilterProxyModel 对 QListView 进行过滤时,拖动顺序的改变通常不会生效,因为 QSortFilterProxyModel 是只读的,不支持修改模型中的数据顺序。要解决这个问题,可以通过以下方法实现:

  1. 操作源模型:在拖动和放置时,将操作应用于 QSortFilterProxyModel 的源模型 (sourceModel)。
  2. 自定义代理模型:重写 QSortFilterProxyModel 的方法以支持拖放和顺序修改。
    下面提供一个完整的实现示例:

实现步骤
1. 自定义 QSortFilterProxyModel
我们需要重写 QSortFilterProxyModel 的 flags 和 moveRows 方法。

#include <QSortFilterProxyModel>

class CustomSortFilterProxyModel : public QSortFilterProxyModel {
    Q_OBJECT

public:
    explicit CustomSortFilterProxyModel(QObject *parent = nullptr)
        : QSortFilterProxyModel(parent) {}

    Qt::ItemFlags flags(const QModelIndex &index) const override {
        if (!index.isValid())
            return Qt::NoItemFlags;

        // 保留拖动和放置的标志
        return QSortFilterProxyModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
    }

    bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count,
                  const QModelIndex &destinationParent, int destinationRow) override {
        if (!sourceModel())
            return false;

        // 将操作映射到源模型
        QModelIndex sourceStart = mapToSource(index(sourceRow, 0, sourceParent));
        QModelIndex sourceEnd = mapToSource(index(sourceRow + count - 1, 0, sourceParent));
        QModelIndex sourceDest = mapToSource(index(destinationRow, 0, destinationParent));

        return sourceModel()->moveRows(sourceStart.parent(), sourceStart.row(), count,
                                       sourceDest.parent(), sourceDest.row());
    }
};

2. 主窗口代码

#include <QApplication>
#include <QListView>
#include <QStandardItemModel>
#include "CustomSortFilterProxyModel.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // 创建源模型
    QStandardItemModel *sourceModel = new QStandardItemModel;
    QStringList items = {"Item 1", "Item 2", "Item 3", "Item 4"};
    for (const QString &itemText : items) {
        QStandardItem *item = new QStandardItem(itemText);
        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
        sourceModel->appendRow(item);
    }

    // 创建代理模型并设置过滤规则
    CustomSortFilterProxyModel *proxyModel = new CustomSortFilterProxyModel;
    proxyModel->setSourceModel(sourceModel);
    proxyModel->setFilterRole(Qt::DisplayRole);
    proxyModel->setFilterRegExp(QRegExp("Item [13]", Qt::CaseInsensitive));  // 仅显示 Item 1 和 Item 3

    // 创建 QListView
    QListView *listView = new QListView;
    listView->setModel(proxyModel);
    listView->setDragDropMode(QAbstractItemView::InternalMove);
    listView->setDefaultDropAction(Qt::MoveAction);
    listView->setDragEnabled(true);
    listView->setAcceptDrops(true);
    listView->setDropIndicatorShown(true);

    listView->show();
    return app.exec();
}

注意事项

  1. 源模型更新:拖放操作会更新源模型中的顺序,但只会影响过滤后的项在视图中的显示顺序。
  2. 数据同步:确保源模型和代理模型的数据状态同步,避免因过滤条件改变导致异常行为。

标签:QListView,Qt,模型,Item,listView,QSortFilterProxyModel,QModelIndex
From: https://www.cnblogs.com/nemochen/p/18566360

相关文章

  • vue3下el-carousel的card模式下设置item之间的间距
    <el-carouselref="refCarousel"class="wh100Per":autoplay="false":loop="true"type="card"arrow="never"indicator-position="none"@change="priceChange">&......
  • 【Qt】QStandardItem和QStandardItemModle以及QModelIndex的关系
    在Qt框架中,QStandardItem、QStandardItemModel和QModelIndex是用来处理表格和数据视图的关键类。以下是它们之间的关系和用途:QStandardItemQStandardItem是QStandardItemModel中用来表示单个项的类。它可以包含数据(如文本、图标、复选框状态等)和子项(用于树结构)。QSt......
  • WPF ListBox IsSynchronizedWithCurrentItem True ScrollIntoView via behavior CallM
    <ListBoxGrid.Column="0"ItemContainerStyle="{StaticResourcelbxItemContainerStyle}"ItemsSource="{BindingBooksCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"IsSynchronizedWith......
  • 电商API数据接口1688alibaba接口item_search_shop-获得店铺的所有商品接入演示
    一、接口功能item_search_shop接口是1688阿里巴巴提供的获取店铺所有商品的API接口,用户可以通过输入店铺ID,获取该店铺的所有商品信息。二、接口调用请求参数:seller_nick=b2b-2200733087881719de&start_price=0&end_price=0&q=&page=1&cid=参数说明:seller_nick:sid或者加密后的_sopi......
  • PbootCMS生成的sitemap.xml中增加tag标签链接
    要在PBootCMS中实现在sitemap.xml中包含标签(tag)链接,可以通过修改相关模型和控制器来实现。以下是详细的步骤和代码示例:步骤修改SitemapModel类在 SitemapModel.php 中增加获取指定分类标签的方法。修改SitemapController类在 SitemapController.php 中增加处理......
  • handycontrol的CheckComboBox的SelectedItems顺序
    【实现效果】【问题】handycontrol的CheckComboBox没有SelectedItems这一项:当保存下来的选中项,需要在下次打开的时候加载,而handycontrol的CheckComboBox没有SelectedItems,于是就先解决如何拿到绑定SelectedItems,通过附加属性的方式:WPF使用附加属性来绑定ListBox的SelectedIt......
  • WPF overlay on the icon in the taskbar via TaskbarItemInfo
    <Windowx:Class="WpfApp372.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft......
  • Qt 模型视图(四):代理类QAbstractItemDelegate
    文章目录Qt模型视图(四):代理类`QAbstractItemDelegate`1.基本概念1.1.使用现有代理1.2.一个简单的代理2.提供编辑器3.向模型提交数据4.更新编辑器的几何图形5.编辑提示Qt模型视图(四):代理类QAbstractItemDelegate​模型/视图结构是一种将数据存储和界面展示分......
  • QTreeView+QStyledItemDelegate实现编辑名称功能
    1.需求描述点击编辑按钮,进入编辑状态,点击确认和取消按钮退出编辑状态(1)  重写代理createEditor函数这个函数是代理触发编辑信号后,自动创建编辑界面的widget对象,覆盖在item上;EmptyTreeItem就是我们自定义的编辑控件,包括输入框,确认和取消按钮;QWidget*TreeTaskDelegate::......
  • QStandardItem先设置图标再插入QTreeView会影响插入性能
    所有的界面显示都交代理去绘制,否则会影响插入性能;一开始打算将类型图标通过QStandardItem创建时传给QStandardItem,在插入到model中,后来发现这样会降低插入的性能;pItem=newQStandardItem(QIcon(":/foldericon.svg"),info.value("name").toString());改成用代理QStyledItemDel......