You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免QListView内部拖拽移动时出现闪烁问题

QListView内部拖拽移动时重复项目闪烁问题解决

问题描述

将QListView与QStandardItemModel关联,启用内部拖拽移动(QAbstractItemView::InternalMove)时,拖拽过程中视图会瞬间显示重复项目,导致明显闪烁,且列表项目越多,该现象越频繁:

before:   during:   after:

item 1    item 1    item 2
item 2    item 2    item 1
item 3    item 1    item 3
          item 3

尝试过调整QStandardItemModel::insertRows()、QListView::viewport()->setUpdatesEnabled()、QListView::blockSignals()等方法,均未解决问题。

解决方案

方法一:自定义QListView,控制拖拽过程的视图更新

重写QListView的拖拽事件处理方法,在拖拽过程中临时关闭视图更新,避免临时插入的项目被渲染:

#include <QApplication>
#include <QListView>
#include <QStandardItemModel>
#include <QDragMoveEvent>

class CustomListView : public QListView {
protected:
    void dragMoveEvent(QDragMoveEvent* event) override {
        viewport()->setUpdatesEnabled(false);
        QListView::dragMoveEvent(event);
        viewport()->setUpdatesEnabled(true);
    }

    void dropEvent(QDropEvent* event) override {
        viewport()->setUpdatesEnabled(false);
        QListView::dropEvent(event);
        viewport()->setUpdatesEnabled(true);
        viewport()->update();
    }
};

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

    QStandardItemModel model;
    for (int i = 0; i < 100; ++i) {
        QStandardItem* item = new QStandardItem(QString("item %0").arg(i));
        item->setDropEnabled(false);
        model.appendRow(item);
    }

    CustomListView list;
    list.setModel(&model);
    list.setDragDropMode(QAbstractItemView::InternalMove);
    list.show();
    return a.exec();
}

方法二:重写QStandardItemModel的拖放逻辑,避免临时插入

默认内部拖拽会先插入临时项目再删除原位置项目,重写dropMimeData方法,直接移动项目,从根源消除重复显示:

#include <QApplication>
#include <QListView>
#include <QStandardItemModel>
#include <QMimeData>

class CustomItemModel : public QStandardItemModel {
public:
    using QStandardItemModel::QStandardItemModel;

    bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override {
        if (action != Qt::MoveAction) {
            return QStandardItemModel::dropMimeData(data, action, row, column, parent);
        }

        QModelIndexList sourceIndexes = decodeMimeData(data);
        if (sourceIndexes.isEmpty()) {
            return false;
        }

        int targetRow = row;
        if (targetRow == -1) {
            targetRow = parent.isValid() ? parent.row() : rowCount();
        }

        int sourceRow = sourceIndexes.first().row();
        if (sourceRow < targetRow) {
            targetRow--;
        }

        QStandardItem* item = takeItem(sourceRow);
        insertRow(targetRow, item);

        return true;
    }
};

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

    CustomItemModel model;
    for (int i = 0; i < 100; ++i) {
        QStandardItem* item = new QStandardItem(QString("item %0").arg(i));
        item->setDropEnabled(false);
        model.appendRow(item);
    }

    QListView list;
    list.setModel(&model);
    list.setDragDropMode(QAbstractItemView::InternalMove);
    list.show();
    return a.exec();
}

方法三:优化视图更新策略

通过调整视图的更新模式和滚动设置,减少不必要的重绘,缓解闪烁:

// 在初始化QListView时添加以下配置
list.setViewportUpdateMode(QListView::SmartViewportUpdate);
list.setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
list.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);

内容的提问来源于stack exchange,提问作者MrJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 10:55:55