Qt拖拽事件详解,QTreeView拖放数据传递
1.QT拖拽事件分为两类。
(1)电脑上的文件拖入程序,在程序上放下文件Drop;例如将视频拖入程序进行播放,将图片突入程序进行展示;
(2)程序中界面内部拖放,例如将组织树中的监控点拖入播放窗口进行播放;将一个表格中的人员拖入另外一个表格等;将QTreeview中的item拖动位置,移到不同的组织下;或者将QTableView中item上下移动位置,调整顺序;
2.Qt拖拽类型
(1)复制,源不变,复制一个新的到指定位置;
(2)移动,源删除,将目标移动到新的位置;
3.实现方案
从电脑中拖拽的示例的可以参考https://www.cnblogs.com/bclshuai/p/18320512,本文中主要讲从左侧QTreeView中拖拽一个监控点或者组织去右侧播放窗口去播放;
3.1识别拖的动作,并设置数据到QMimeData
继承QTreeView,重写mousePressEvent函数和mouseMoveEvent函数;mousePressEvent感知鼠标按下操作,结合mouseMoveEvent,当鼠标按下左键,同时移动距离大于系统的拖拽移动距离,表示拖动,很多人在鼠标按下时就创建QDrag对象,这是不对的;应该是要拖动;才触发QDrag;
#ifndef DRAGTREEVIEW_H #define DRAGTREEVIEW_H #include <QTreeView> #include <QMouseEvent> #include <QPoint> class DragTreeView : public QTreeView { Q_OBJECT public: DragTreeView(QWidget *parent); ~DragTreeView(); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); private: QPoint m_dragStartPos; QModelIndex m_currentIndex; }; #endif // DRAGTREEVIEW_H
#include "DragTreeView.h" #include <QApplication> #include <QLine> #include <QMimeData> #include <QDrag> #include "hlog1.h" DragTreeView::DragTreeView(QWidget *parent) : QTreeView(parent) { } DragTreeView::~DragTreeView() { } void DragTreeView::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { QPoint pos = event->pos(); m_currentIndex = indexAt(pos); if (m_currentIndex.isValid()) { m_dragStartPos = pos; } } QTreeView::mousePressEvent(event); } void DragTreeView::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) { int distance = (event->pos() - m_dragStartPos).manhattanLength();//计算距离 int distance2 = QLineF(event->pos(), m_dragStartPos).length();//方式2计算距离 if (distance >= QApplication::startDragDistance()) { //触发QDrag操作 m_currentIndex = currentIndex(); if (m_currentIndex.isValid()) { QVariantMap valu = m_currentIndex.data(Qt::UserRole).toMap(); QString strType = valu.value("type").toString(); QMimeData *mimeData = new QMimeData; if (strType=="3")//拖放监控点播放,传入监控点id { mimeData->setData("Drag/Camera", valu.value("channel_id").toString().toStdString().c_str()); } else if (strType == "1")//拖拽组织进行播放,传入组织id { mimeData->setData("Drag/Group", valu.value("id").toString().toStdString().c_str()); } LOG_INFO("mouse move"); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); drag->exec( Qt::MoveAction);//阻塞住,mouseMoveEvent不会再次触发,QDrag不会重复创建;鼠标释放会结束消息 delete drag; LOG_INFO("drag finish"); } } } }
3.2放的时候,读取拖的时设置到QMimeData的数据
拖拽接收方一定要设置属性setAcceptDrops(true);否则无法接收拖放消息;实现dragEnterEvent函数,在dragEnterEvent中调用event->acceptProposedAction();否则dropEvent无法响应;
#include "deviceview.h" #include "DbPlugin.h" #include<QMimeData> DeviceView::DeviceView(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); if (DbPlugin::instance()->LoadDbPlugin()==-1) { LOG_ERROR("数据库插件加载失败"); } m_pDeviceTree = new DeviceTree(ui.widgetLeft); ui.verticalLayout->addWidget(m_pDeviceTree); } DeviceView::~DeviceView() { } void DeviceView::dragEnterEvent(QDragEnterEvent *event)//接收数据可用性判断,或者接收显示效果设置 { const QMimeData *mimeData = event->mimeData(); int CountUnsurport = 0; QStringList listPath; if (ui.widgetRight->underMouse()) { if (mimeData->hasFormat("Drag/Camera")|| mimeData->hasFormat("Drag/Group")) { event->acceptProposedAction(); // 接受拖动,一定要accept,否则dropEvent无法响应 } } else { event->ignore(); // 接受拖动 } } void DeviceView::dropEvent(QDropEvent *event) { if (ui.widgetRight->underMouse()) { const QMimeData *mimeData = event->mimeData(); if (mimeData->hasFormat("Drag/Camera")) { QString channelid = event->mimeData()->data("Drag/Camera"); //根据监控点id播放监控点 } else if (mimeData->hasFormat("Drag/Group")) { QString groupid = event->mimeData()->data("Drag/Group"); //根据组织播放多个监控点 } } }
自己开发了一个股票智能分析软件,功能很强大,需要的关注微信公众号:QStockView