QTableView自定义拖拽行

QTableView行拖拽实现:多行选择与定制分隔符
本文详细介绍了如何在QTableView中实现实时的行拖拽功能,支持多行选择,同时提供了自定义的拖拽指示器和分隔符样式委托。通过继承QTableView并实现相关方法,展示了如何扩展其拖拽操作到QListView和QTreeView等其他视图。

实现QTableView的行拖拽,支持多行选择拖拽,也可根据需要稍作修改实现QTreeView、QListView等的拖拽效果。

拖拽类实现

继承 QTableView 实现几个拖拽相关的方法
TableView.h

#ifndef TableView_H
#define TableView_H

#include <QObject>
#include <QListView>
#include <QDragEnterEvent>
#include <QDragMoveEvent>
#include <QDragLeaveEvent>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QMimeData>
#include <QDrag>
#include <QDebug>
#include <QTableView>

class TableView : public QTableView
{
   
   
    Q_OBJECT

public:
    explicit TableView(QWidget *parent = nullptr);

    bool isDraging() const {
   
   return IsDraging;}
    int offset() const {
   
   return 12;}
    int highlightedRow() const {
   
   return curHighlightedRow;}
    int dragRow() const {
   
   return curDragRow;}
    static QString myMimeType() {
   
    return QStringLiteral("TableView/text-icon"); }
private:
    //dropIndicator显示与消失
    void updateDropIndicator(int row);
protected:
    void dragEnterEvent(QDragEnterEvent *event) override;
    void dragLeaveEvent(QDragLeaveEvent *event) override;
    void dragMoveEvent(QDragMoveEvent *event) override;
    void dropEvent(QDropEvent *event) override;
    void startDrag(Qt::DropActions supportedActions) override;

private:
    bool IsDraging = false;
    //当前鼠标所在位置 行号
    int curHighlightedRow = -2;
    //被拖拽的行所在的位置
    int oldHighlightedRow = -2;
    //拖拽的行
    int curDragRow = -1;
    //当前鼠标放下所在行
    int curInsertRow = -1;
    //需要删除的旧行(行号)
    QList<int> oldSelectRow;
    //选中的拖拽行
    QList<int> curDragRows;
};

bool compareBarData(const int &barAmount1, const int &barAmount2);

#endif // TableView_H

TableView.cpp

#include "TableView.h"

TableView::TableView(QWidget *parent) :
    QTableView(parent)
{
   
   
    setDragEnabled(true);
    setAcceptDrops(true);
    setEditTriggers(QAbstractItemView::NoEditTriggers);

    this->setStyleSheet(
        "QListView::Item{height:20px;}"
    );
    //列撑满整个表格
    this->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    //去掉表格边框线
    this->setShowGrid(false);
    //整行选择
    this->setSelectionBehavior(QAbstractItemView::SelectRows);
    //按住ctrl多选
    this->setSelectionMode(QAbstractItemView::ExtendedSelection);
}

void TableView::dragEnterEvent(QDragEnterEvent *event)
{
   
   
    TableView *source = qobject_cast<TableView *>(event->source());
    if (source && source == this) {
   
   
        IsDraging = true;  //IsDraging(标志位)判断是否正在拖拽
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}

void TableView::dragLeaveEvent(QDragLeaveEvent *event)
{
   
   
    oldHighlightedRow = curHighlightedRow;
    curHighlightedRow = -2;
    //刷新以使dropIndicator消失,
    updateDropIndicator(oldHighlightedRow);
    IsDraging = false;
    curInsertRow = -1;
    event->accept();
}
//dropIndicator显示与消失
void TableView::updateDropIndicator(int row)
{
   
   
    //这里用的是update(QModelIndex),这里也可以使用update(QRect),在表格所有列绘制分隔符
    for (int updateColI = 0; updateColI < this->model()->columnCount();updateColI++) {
   
   
        //刷新新区域使dropIndicator显示
        update(model()->index(row, updateColI));
        update(model()->index(row + 1, updateColI));
    }
}
void TableView::dragMoveEvent(QDragMoveEvent *event)
{
   
   
    TableView *source = qobject_cast<TableView *>(event->source());
    if (source && source == this) {
   
   
        oldHighlightedRow = curHighlightedRow;
        curHighlightedRow = indexAt(event->pos() - QPoint(0, offset())).row();

        //offset() = 9 = rowHeight / 2 - 1,其中 rowHeight 是行高
        if(event->pos().y() >= offset()){
   
   
            if(oldHighlightedRow != curHighlightedRow){
   
   
                //刷新以使dropIndicator消失
                updateDropIndicator(oldHighlightedRow);

                //刷新新区域使dropIndicator显示
                updateDropIndicator(curHighlightedRow
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值