#include "CAutoListView.h" #include #include CAutoListView::CAutoListView(QWidget *parent) :QListView(parent) { // setSelectionMode(QAbstractItemView::ExtendedSelection); // setDragEnabled(true); // setAcceptDrops(true); // setDropIndicatorShown(true); // setDefaultDropAction(Qt::MoveAction); } void CAutoListView::mousePressEvent(QMouseEvent *event) { if(event->buttons() & Qt::LeftButton){ startPos = event->pos(); } QListView::mousePressEvent(event); } void CAutoListView::mouseReleaseEvent(QMouseEvent *event) { QListView::mouseReleaseEvent(event); if((event->pos() - startPos).manhattanLength() > 5) return; QModelIndex index = indexAt(event->pos()); setCurrentIndex(index); //鼠标relesse时才选中 } void CAutoListView::mouseMoveEvent(QMouseEvent *event) { QListView::mouseMoveEvent(event); if(event->buttons() & Qt::LeftButton){ if((event->pos() - startPos).manhattanLength() < QApplication::startDragDistance()) return; QModelIndex theDragIndex = indexAt(startPos); theDragRow = theDragIndex.row(); setCurrentIndex(theDragIndex); //拖拽即选中 QStandardItemModel *listModel = qobject_cast(model()); QStandardItem *theDragItem = static_cast(listModel->item(theDragRow)); //[1]把拖拽数据放在QMimeData容器中 QString text = theDragItem->text(); QByteArray itemData; QDataStream dataStream(&itemData, QIODevice::WriteOnly); dataStream << text; QMimeData *mimeData = new QMimeData; mimeData->setData(myMimeType(), itemData); //[1] // 创建 QDrag 对象并设置拖拽数据和预览图 QPixmap pixmap = QPixmap(100, 50); // 创建一个固定大小的预览图 pixmap.fill(Qt::transparent); // 透明背景 QPainter painter(&pixmap); painter.setPen(Qt::black); painter.setFont(QFont("Arial", 10)); painter.drawText(pixmap.rect(), Qt::AlignCenter, text); // 在图像上绘制文本 QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); drag->setPixmap(pixmap); drag->setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2)); // 设置热点位置为图像中心 //删除的行需要根据theInsertRow和theDragRow的大小关系来判断(这个也是我根据实际情况测试发现的) if(drag->exec(Qt::MoveAction) == Qt::MoveAction){ int theRemoveRow = -1; if(theInsertRow < theDragRow) theRemoveRow = theDragRow + 1; else theRemoveRow = theDragRow; model()->removeRow(theRemoveRow); } } } void CAutoListView::dragEnterEvent(QDragEnterEvent *event) { CAutoListView *source = qobject_cast(event->source()); if (source && source == this) { //IsDraging(标志位)判断是否正在拖拽 IsDraging = true; event->setDropAction(Qt::MoveAction); event->accept(); } } void CAutoListView::dragLeaveEvent(QDragLeaveEvent *event) { oldHighlightedRow = theHighlightedRow; theHighlightedRow = -2; //之前QListWidget用的是update(QRect),这里用的是update(QModelIndex),当然这里也可以使用update(QRect),只是想换一种方法而已 update(model()->index(oldHighlightedRow, 0)); //UpRow update(model()->index(oldHighlightedRow + 1, 0)); //DownRow IsDraging = false; //IsDraging(标志位)判断是否正在拖拽 theInsertRow = -1; event->accept(); } void CAutoListView::dragMoveEvent(QDragMoveEvent *event) { CAutoListView *source = qobject_cast(event->source()); if (source && source == this) { oldHighlightedRow = theHighlightedRow; theHighlightedRow = indexAt(event->pos() - QPoint(0, offset())).row(); //offset() = 19 = 40 / 2 - 1,其中40是行高 if(event->pos().y() >= offset()){ if(oldHighlightedRow != theHighlightedRow){ //刷新旧区域使dropIndicator消失 update(model()->index(oldHighlightedRow, 0)); update(model()->index(oldHighlightedRow + 1, 0)); //刷新新区域使dropIndicator显示 update(model()->index(theHighlightedRow, 0)); update(model()->index(theHighlightedRow + 1, 0)); }else{ update(model()->index(theHighlightedRow, 0)); update(model()->index(theHighlightedRow + 1, 0)); } theInsertRow = theHighlightedRow + 1; }else{ theHighlightedRow = -1; update(model()->index(0, 0)); update(model()->index(1, 0)); theInsertRow = 0; } event->setDropAction(Qt::MoveAction); event->accept(); } } void CAutoListView::dropEvent(QDropEvent *event) { CAutoListView *source = qobject_cast(event->source()); if (source && source == this){ IsDraging = false; //IsDraging(标志位)判断是否正在拖拽 oldHighlightedRow = theHighlightedRow; theHighlightedRow = -2; //刷新旧区域使dropIndicator消失 update(model()->index(oldHighlightedRow, 0)); update(model()->index(oldHighlightedRow + 1, 0)); if(theInsertRow == theDragRow || theInsertRow == theDragRow + 1) return; //这里我像QListWidget那样调用父类dropEvent(event)发现不起作用(原因尚不明),没办法,只能删除旧行,插入新行 //if(theSelectedRow == theDragRow){ //QListView::dropEvent(event); //return; //} QString text; QIcon icon, icon_hover; QByteArray itemData = event->mimeData()->data(myMimeType()); QDataStream dataStream(&itemData, QIODevice::ReadOnly); dataStream >> text; model()->insertRow(theInsertRow); QStandardItemModel *listModel = qobject_cast(model()); listModel->setItem(theInsertRow, 0, new QStandardItem(text)); setCurrentIndex(model()->index(theInsertRow, 0)); //插入行保持选中状态 event->setDropAction(Qt::MoveAction); event->accept(); } }