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");
            //根据组织播放多个监控点
        }    
    }
}

 

posted @ 2024-09-20 17:27  一字千金  阅读(253)  评论(0编辑  收藏  举报