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

Qt框架中QGraphicsScene拖拽事件的正确实现方法

跳棋项目中Qt图形项拖拽事件未触发的解决方案

核心问题分析

你的拖拽事件未触发,主要是因为缺少几个关键前提设置:

  • 图形项未启用拖拽接收(acceptDrops(true))
  • 未手动启动拖拽流程(通过QDrag类触发)
  • ItemIsMovable标志会和自定义拖拽逻辑冲突,需禁用

以下是修正后的完整实现代码:


Pawn类修正(棋子类)

首先在头文件添加私有成员QPointF m_dragStartPos;,然后实现关键方法:

#include <QDrag>
#include <QMimeData>
#include <QPainter>

Pawn::Pawn(int x, int y, int rozmiar) : QGraphicsEllipseItem(x, y, rozmiar, rozmiar) {
    setAcceptDrops(true); // 必须开启,才能接收拖拽事件
    kolor = QBrush(Qt::darkRed);
    setBrush(kolor);
    setFlag(QGraphicsItem::ItemIsSelectable); // 保留选中功能,移除ItemIsMovable
}

void Pawn::mousePressEvent(QGraphicsSceneMouseEvent *event) {
    QGraphicsEllipseItem::mousePressEvent(event);
    if (event->button() == Qt::LeftButton) {
        m_dragStartPos = event->pos(); // 记录鼠标相对棋子的点击位置
    }
}

void Pawn::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
    if (event->buttons() & Qt::LeftButton) {
        QPointF diff = event->pos() - m_dragStartPos;
        // 过滤点击抖动,达到拖拽阈值才触发
        if (diff.manhattanLength() > QApplication::startDragDistance()) {
            QDrag *drag = new QDrag(event->widget());
            QMimeData *mimeData = new QMimeData();
            
            // 自定义MIME类型,传递棋子指针(确保唯一性)
            mimeData->setData("application/x-checkers-pawn", 
                             QByteArray::fromRawData(reinterpret_cast<char*>(this), sizeof(this)));
            
            drag->setMimeData(mimeData);
            
            // 生成拖拽时的棋子图标
            QPixmap pixmap(boundingRect().size().toSize());
            pixmap.fill(Qt::transparent);
            QPainter painter(&pixmap);
            painter.setBrush(kolor);
            painter.drawEllipse(boundingRect());
            drag->setPixmap(pixmap);
            
            // 启动拖拽,设置为移动模式
            drag->exec(Qt::MoveAction);
        }
    }
    QGraphicsEllipseItem::mouseMoveEvent(event);
}

void Pawn::dragEnterEvent(QGraphicsSceneDragDropEvent *event) {
    qDebug() << "Pawn dragEnterEvent triggered";
    if (event->mimeData()->hasFormat("application/x-checkers-pawn")) {
        event->acceptProposedAction();
    }
}

void Pawn::dragLeaveEvent(QGraphicsSceneDragDropEvent *event) {
    qDebug() << "Pawn dragLeaveEvent triggered";
    event->accept();
}

void Pawn::dropEvent(QGraphicsSceneDragDropEvent *event) {
    qDebug() << "Pawn dropEvent triggered";
    if (event->mimeData()->hasFormat("application/x-checkers-pawn")) {
        Pawn *sourcePawn = reinterpret_cast<Pawn*>(event->mimeData()->data("application/x-checkers-pawn").data());
        if (sourcePawn != this) {
            // 实现棋子交换逻辑
            QPointF tempPos = sourcePawn->pos();
            sourcePawn->setPos(pos());
            setPos(tempPos);
        }
        event->acceptProposedAction();
    }
}

Tile类修正(棋盘格子类)

确保开启拖拽接收,并实现Drop逻辑:

Tile::Tile(QBrush color, int x, int y, int col, int row) : QGraphicsRectItem(x, y, 60, 60) {
    setAcceptDrops(true); // 开启拖拽接收
    this->color = color;
    this->col = col;
    this->row = row;
    this->pawn = nullptr;
    setBrush(color);
}

void Tile::dragEnterEvent(QGraphicsSceneDragDropEvent *event) {
    qDebug() << "Tile dragEnterEvent triggered";
    if (event->mimeData()->hasFormat("application/x-checkers-pawn") && !isPawnSet()) {
        event->acceptProposedAction();
    }
}

void Tile::dropEvent(QGraphicsSceneDragDropEvent *event) {
    qDebug() << "Tile dropEvent triggered";
    if (event->mimeData()->hasFormat("application/x-checkers-pawn") && !isPawnSet()) {
        Pawn *sourcePawn = reinterpret_cast<Pawn*>(event->mimeData()->data("application/x-checkers-pawn").data());
        // 将棋子移动到格子中心
        sourcePawn->setPos(boundingRect().center() - sourcePawn->boundingRect().center());
        setPawn(sourcePawn);
        event->acceptProposedAction();
    }
}

额外注意事项

  1. 移除ItemIsMovable标志:该标志会让Qt自动处理图形项移动,覆盖自定义拖拽逻辑
  2. 场景与视图设置:确保QGraphicsScene已正确绑定到QGraphicsView,视图无需特殊拖拽模式设置
  3. MIME类型唯一性:自定义类型避免与系统拖拽类型冲突,建议使用项目相关命名(如application/x-checkers-pawn)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 17:53:20