C++ QT QDrag的使用

  • 在 QTreeView 发起拖拽(用 QDrag + QMimeData),把需要传递的标识/数据放到 mime 中(不要直接传裸指针)。
  • 播放窗口设置 setAcceptDrops(true),重载 dragEnterEvent/dragMoveEvent/dropEvent,接收 mime 并在拖拽经过时(dragMoveEvent)做感知与临时反馈,dropEvent 做最终处理。
  • 在 dragMoveEvent 可通过 event->source() 得到拖拽来源(可 qobject_cast 回 QTreeView)并根据 event->pos() 做高亮/提示/播放变化等。

示例代码(Qt5/6,简化版)

  1. 自定义 TreeView 发起拖拽(也可重写 startDrag):

    class MyTreeView : public QTreeView {
    QPoint m_dragStart;
    void mousePressEvent(QMouseEvent *e) override {
    if (e->button() == Qt::LeftButton) m_dragStart = e->pos();
    QTreeView::mousePressEvent(e);
    }
    void mouseMoveEvent(QMouseEvent *e) override {
    if (!(e->buttons() & Qt::LeftButton)) return;
    if ((e->pos() - m_dragStart).manhattanLength() < QApplication::startDragDistance()) return;
    QModelIndex idx = indexAt(m_dragStart);
    if (!idx.isValid()) return;

    复制代码
         // 构造 mime 数据(用自定义格式)
         QMimeData *mime = new QMimeData;
         QByteArray ba;
         QDataStream ds(&ba, QIODevice::WriteOnly);
         ds << idx.data(Qt::UserRole).toString(); // 或其他标识
         mime->setData("application/x-myitem", ba);
    
         QDrag drag(this);
         drag.setMimeData(mime);
         drag.setPixmap(QPixmap(":/icons/item.png"));
         drag.setHotSpot(QPoint(10,10));
         drag.exec(Qt::CopyAction | Qt::MoveAction);
     }

    };

  2. 播放窗口接收并感知拖拽:

    class PlayWidget : public QWidget {
    void init() { setAcceptDrops(true); }
    void dragEnterEvent(QDragEnterEvent *e) override {
    if (e->mimeData()->hasFormat("application/x-myitem")) {
    e->acceptProposedAction();
    // 可在此做一次入场高亮
    showHoverFeedback(e->pos());
    } else {
    e->ignore();
    }
    }
    void dragMoveEvent(QDragMoveEvent *e) override {
    if (e->mimeData()->hasFormat("application/x-myitem")) {
    e->acceptProposedAction();
    // 实时反馈:例如高亮区域、显示提示、预览等
    updateHoverRegion(e->pos());
    // 可访问 source(若需读取源控件信息)
    const QObject *src = e->source();
    if (const QTreeView tv = qobject_cast<const QTreeView>(src)) {
    // 需要时与源交互(只读)
    }
    } else {
    e->ignore();
    }
    }
    void dropEvent(QDropEvent *e) override {
    if (!e->mimeData()->hasFormat("application/x-myitem")) { e->ignore(); return; }
    QByteArray ba = e->mimeData()->data("application/x-myitem");
    QDataStream ds(&ba, QIODevice::ReadOnly);
    QString id; ds >> id;
    // 根据 id 做实际动作(切换视频、拖入标注、播放相关变化等)
    handleDropItem(id, e->pos());
    e->acceptProposedAction();
    }
    };

实现细节与建议

  • mime 格式用自定义 MIME type(如 application/x-myitem),内容用 QDataStream 序列化标识(避免裸指针)。
  • 若希望拖拽过程显示浮动预览,可用 QDrag::setPixmap 或在播放窗口 dragMoveEvent 绘制临时 overlay。
  • 如需阻止 QTreeView 的默认拖拽行为,可在 model/view 设置 setDragEnabled(false) 然后用自定义逻辑,或重写 startDrag。
  • 若跨进程或安全限制,不应依赖 event->source() 强转换;尽量用 mime 携带必要数据。
  • 调试:注意 QApplication::startDragDistance() 与 drag/drop 的接受动作(acceptProposedAction)。
相关推荐
一只爱学习的小鱼儿12 分钟前
在QT中使用饼状图进行数据分析
开发语言·qt·数据分析
小徐不徐说1 小时前
避坑指南:Qt 中 Lambda 表达式崩溃原因与高效使用实践
数据库·c++·qt·面试
嘿嘿潶黑黑2 小时前
Qt中的Q_PROPERTY宏
开发语言·qt
hqwest4 小时前
码上通QT实战20--监控页面12-获取灯珠状态
qt·modbus·开关量·功能码01·线圈状态
艾莉丝努力练剑5 小时前
【QT】环境搭建收尾:认识Qt Creator
运维·开发语言·c++·人工智能·qt·qt creator·qt5
Larry_Yanan5 小时前
Qt安卓开发(二)摄像头打开
android·开发语言·数据库·c++·qt·ui
枫叶丹46 小时前
【Qt开发】Qt系统(六)-> Qt 线程安全
c语言·开发语言·数据库·c++·qt·安全
_OP_CHEN6 小时前
【从零开始的Qt开发指南】(二十一)Qt 网络编程封神指南:UDP/TCP/HTTP 全场景实战
网络·qt·http·udp·tcp·前端开发·qt网络
郝学胜-神的一滴7 小时前
深入理解Qt中的坐标系统:鼠标、窗口与控件位置详解
开发语言·c++·qt·程序人生
hqwest18 小时前
码上通QT实战12--监控页面04-绘制6个灯珠及开关
开发语言·qt·qpainter·qt事件·stackedwidget