要实现QTableView内部拖拽和QTableView相互拖拽只需要继承QTableView,然后重写
void dropEvent(QDropEvent *event);
void startDrag(Qt::DropActions supportedActions);
这两个方法即可实现相应的功能。主要代码如下图所示
#ifndef TABLEVIEW_H
#define TABLEVIEW_H
#include <QTableView>
#include <QMouseEvent>
#include <QDragEnterEvent>
#include<QByteArray>
class TableView : public QTableView
{
Q_OBJECT
public:
TableView(QWidget *parent = nullptr);
protected:
void dropEvent(QDropEvent *event);
void startDrag(Qt::DropActions supportedActions);
private:
QPixmap renderToPixmap(const QModelIndex index);
signals:
public slots:
};
#endif // TABLEVIEW_H
#include "tableview.h"
#include<QStandardItemModel>
#include<QStandardItem>
#include<QDrag>
#include<QMimeData>
#include<QWindow>
#include<QPainter>
#include<QByteArray>
#include<QDebug>
TableView::TableView(QWidget *parent) : QTableView(parent)
{
setDragDropMode(QAbstractItemView::DragDrop);
setDragEnabled(true);
setAcceptDrops(true);
setDropIndicatorShown(true);
setMouseTracking(true);
setDragDropOverwriteMode(true);
QStandardItemModel* model=new QStandardItemModel(this);
for(int row=0;row<10;row++)
{
for(int column=0;column<5;column++)
{
QStandardItem* item=new QStandardItem(QString("%1,%2").arg(row).arg(column));
if(row%2==0)
{
item->setIcon(QIcon("://icon1.png"));
}
else
{
item->setIcon(QIcon("://icon2.png"));
}
model->setItem(row,column,item);
}
}
setModel(model);
resize(600,500);
}
void TableView::dropEvent(QDropEvent *event)
{
QByteArray itemData=event->mimeData()->data("application/x-qabstractitemmodeldatalist");
QDataStream stream(&itemData, QIODevice::ReadOnly);
int row,col;
QMap<int, QVariant> roleDataMap;
while (!stream.atEnd())
{
stream >> row >> col >> roleDataMap;
//qDebug() << "enter-----row: " << row << " col :" << col << " data:"<< roleDataMap ;
QString text=roleDataMap.value(0).toString();
QIcon icon=roleDataMap.value(1).value<QIcon>();
QModelIndex index=this->indexAt(this->viewport()->mapFromGlobal(QCursor::pos()));
if(index.isValid())
{
// qDebug()<<index;
this->model()->setData(index,roleDataMap.value(0),Qt::EditRole);
this->model()->setData(index,roleDataMap.value(1),Qt::DecorationRole);
setCurrentIndex(index);
}
else
{
qDebug()<<"drop invalid";
}
}
}
void TableView::startDrag(Qt::DropActions supportedActions)
{
QModelIndexList indexes=this->selectedIndexes();
if(indexes.count()>0)
{
QMimeData *data=this->model()->mimeData(indexes);
if (!data)
return;
QRect rect;
QPixmap pixmap = renderToPixmap(indexes[0]);
rect.adjust(horizontalOffset(), verticalOffset(), 0, 0);
QDrag *drag = new QDrag(this);
drag->setPixmap(pixmap);
drag->setMimeData(data);
drag->setHotSpot(QPoint(pixmap.width() / 2, pixmap.height()/ 2));
drag->exec(supportedActions|Qt::CopyAction|Qt::MoveAction);
QByteArray itemData= data->data("application/x-qabstractitemmodeldatalist");
QDataStream stream(&itemData, QIODevice::ReadOnly);
int row,col;
QMap<int, QVariant> roleDataMap;
while (!stream.atEnd())
{
stream >> row >> col >> roleDataMap;
QModelIndex oldIndex=this->model()->index(row,col);
this->model()->setData(oldIndex,"",Qt::EditRole);
this->model()->setData(oldIndex,"",Qt::DecorationRole);
//qDebug() << "row: " << row << " col :" << col << " data:"<< roleDataMap ;
QString text=roleDataMap.value(0).toString();
QIcon icon=roleDataMap.value(1).value<QIcon>();
QModelIndex index=this->indexAt(this->viewport()->mapFromGlobal(QCursor::pos()));
if(index.isValid())
{
// qDebug()<<index;
this->model()->setData(index,roleDataMap.value(0),Qt::EditRole);
this->model()->setData(index,roleDataMap.value(1),Qt::DecorationRole);
setCurrentIndex(index);
}
else
{
qDebug()<<"inner move invalid";
}
}
}
}
QPixmap TableView::renderToPixmap(const QModelIndex index)
{
const QRect viewportRect = this->viewport()->rect();
const QRect indexRect = this->visualRect(index);
QRect rect;
if(indexRect.intersects(viewportRect)) {
rect |= indexRect;
}
rect&=viewportRect;
qreal scale = 1.0f;
QWidget *window = this->window();
if (window) {
QWindow *windowHandle = window->windowHandle();
if (windowHandle)
scale = windowHandle->devicePixelRatio();
}
QPixmap pixmap(rect.size() * scale);
pixmap.setDevicePixelRatio(scale);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
QStyleOptionViewItem option = this->viewOptions();
//option.state |= QStyle::State_Selected;
option.rect=indexRect.translated(-rect.topLeft());
this->itemDelegate()->paint(&painter, option, index);
return pixmap;
}