Qt拖拽事件详解及代码实现

Qt拖拽事件详解及代码实现

前言

qt拖拽事件是一项非常常用并且非常好用的功能,拖拽实际上是一种信息传递的载体,其目的是将信息从一个对象传递给另一个对象。通过拖拽可以简化文件打开或业务操作流程,qt初学者学会拖拽事件后就可以马上开发出许多有趣的项目,本文以一个简单的示例来介绍拖拽事件功能。

项目描述

本项目通过搭建两个对话框,一个作为拖拽信息来源,另一个作为拖拽信息目标,介绍拖拽事件,主要实现了字符串信息的传递,并且对拖拽过程的动作进行了探索。

代码结构简介

DragDropWidget类实现了拖拽发起对话框,主要是重写了鼠标事件函数,用于设置拖拽搭载的信息,这里就是一个字符串,实际上也可以是自定义的类或者其他对象。代码详见dragdropwidget.h及dragdropwidget.cpp。
AcceptWidget类实现了拖拽接收对话框,主要重写了拖拽进入及拖拽放置函数,用于处理拖拽进入的信息。代码详见acceptwidget.h及acceptwidget.cpp。

代码详解

dragdropwidget.h

#ifndef DRAGDROPWIDGET_H
#define DRAGDROPWIDGET_H

#include <QWidget>

class DragDropWidget : public QWidget
{
    Q_OBJECT

public:
    DragDropWidget(QWidget *parent = 0);
    ~DragDropWidget();

protected:
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
private:
    QPoint m_DragStartPos;
};

#endif // DRAGDROPWIDGET_H

在DragDropWidget 类的头文件中声明了经典鼠标处理三事件,并声明了一个成员变量m_DragStartPos,用于记录拖拽的起始位置。
dragdropwidget.cpp

#include "dragdropwidget.h"

#include <QStyle>
#include <QStyleOption>
#include <QIcon>
#include <QDrag>
#include <QMimeData>
#include <QMouseEvent>
#include <QApplication>

#include <QLabel>
#include <QDebug>

DragDropWidget::DragDropWidget(QWidget *parent)
    : QWidget(parent)
{
    m_DragStartPos=QPoint(-1,-1);
    setWindowTitle("dragwidget");
}

DragDropWidget::~DragDropWidget()
{

}

void DragDropWidget::mousePressEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton)
    {
        m_DragStartPos=event->pos();
        printf("====mousepressed\n");
    }
}

void DragDropWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton)
    {
        if(QLineF(event->pos(),m_DragStartPos).length()<QApplication::startDragDistance())
        {
            printf("distence less\n");
            return;
        }
        printf("===process drag\n");
        QDrag *drag=new QDrag(this);
        QMimeData *mimedata=new QMimeData;

        mimedata->setData("localtype","teststr");
        drag->setMimeData(mimedata);

        QStyle *style = QApplication::style();
        QStyleOption option;
        QIcon icon = style->standardIcon(QStyle::SP_DialogOpenButton, &option, nullptr);
        QPixmap pixmap = icon.pixmap(32, 32);
        drag->setPixmap(pixmap);
        drag->setHotSpot(QPoint(10,10));
        Qt::DropAction dropaction=drag->exec(Qt::CopyAction); //| Qt::MoveAction
    }
}

void DragDropWidget::mouseReleaseEvent(QMouseEvent *event)
{
    QWidget::mouseReleaseEvent(event);
}

在构造函数中,对拖拽起始位置进行了初始化,并设置了窗口名称;在mousePressEvent函数中,判断了是否为左键点击,并更新了拖拽起始位置;在mouseMoveEvent函数中,首先判断拖拽事件中左键是否在移动中保持了点击状态,

if (event->buttons() & Qt::LeftButton)

event->buttons()获取在移动过程中的所有保持点击状态的按钮,和Qt::LeftButton做&运算,用于判断左键是否在这些按钮中,据此判断左键是否在移动中保持点击状态;

if(QLineF(event->pos(),m_DragStartPos).length()<QApplication::startDragDistance())

通过判断当前鼠标所在位置与起始拖拽点之间的距离是否超过一定范围来判断拖拽是否有效,QApplication::startDragDistance()为10px;

        QDrag *drag=new QDrag(this);
        QMimeData *mimedata=new QMimeData;

首先构造了QDrag及QMimeData对象;

        mimedata->setData("localtype","teststr");

然后对QMimeData对象设置了数据,这里setData有两个参数,这里用的是通用的数据设置绑定方法,第一个参数“localtype”为设置的数据类型,这里可以自定义一个字符串作为类型,第二个参数即为传递的数据,第二个参数的类型为QByteArray,也就是说,传进来的内容将会被转为QByteArray类型,后续在解析时可以将QByteArray还原为传入的类型。

drag->setMimeData(mimedata);

这里将QMimeData对象绑定到QDrag对象,借助QDrag对象实现数据的传递;

        QStyle *style = QApplication::style();
        QStyleOption option;
        QIcon icon = style->standardIcon(QStyle::SP_DialogOpenButton, &option, nullptr);
        QPixmap pixmap = icon.pixmap(32, 32);
        drag->setPixmap(pixmap);
        drag->setHotSpot(QPoint(10,10));

这里实际上是对QDrag对象设置一个图标,用于在拖拽过程中显示,这里使用了qt内置的标准图标,setHotSpot函数用于指定拖拽点位于图标的位置;

Qt::DropAction dropaction=drag->exec(Qt::CopyAction); 

最后执行了QDrag对象的exec函数,这里可以指定拖拽动作类型,不同的类型会影响后面在接收拖拽时的显示,例如Qt::CopyAction在接收拖拽时则会在之前设置的图标右下角显示一个“+”号;
acceptwidget.h

#ifndef ACCEPTWIDGET_H
#define ACCEPTWIDGET_H

#include <QWidget>

class QDragEnterEvent;
class QDropEvent;

class AcceptWidget : public QWidget
{
    Q_OBJECT
public:
    explicit AcceptWidget(QWidget *parent = nullptr);
protected:
    void dragEnterEvent(QDragEnterEvent *event) override;
    void dropEvent(QDropEvent *event) override;

signals:

public slots:
};

#endif // ACCEPTWIDGET_H

AcceptWidget 类的头文件中声明了处理接收拖拽事件的dragEnterEvent及dropEvent函数,这两个函数是处理接收拖拽事件最基本的两个函数,dragEnterEvent用于处理进入本窗口时需要做出的操作,例如判断拖拽进入的内容是否需要接受等,dropEvent函数用于处理确认接收拖拽事件的操作,主要是获取QMimeData;
acceptwidget.cpp

#include "acceptwidget.h"

#include <QStyle>
#include <QStyleOption>
#include <QIcon>
#include <QLabel>
#include <QMimeData>
#include <QDropEvent>
#include <QDragEnterEvent>
#include <QApplication>

AcceptWidget::AcceptWidget(QWidget *parent) : QWidget(parent)
{
    setWindowTitle("Drop Widget");
    this->setAcceptDrops(true);
}

void AcceptWidget::dragEnterEvent(QDragEnterEvent *event)
{
    event->acceptProposedAction();
    printf("drag enter\n");
}

void AcceptWidget::dropEvent(QDropEvent *event)
{
    printf("grop enter\n");
    const QMimeData *mimedata= event->mimeData();
    if(mimedata->hasFormat("localtype"))
    {
        QByteArray mimestr=mimedata->data("localtype");
        std::string sstr=mimestr.toStdString();
        printf("=====sstring==%s\n",sstr.c_str());

        QLabel *label=new QLabel(this);
        QStyle *style = QApplication::style();
        QStyleOption option;
        QIcon icon = style->standardIcon(QStyle::SP_DialogOpenButton, &option, nullptr);
        QPixmap pixmap = icon.pixmap(32, 32);
        label->setPixmap(pixmap);
        label->move(event->pos());
        label->show();
    }
}

AcceptWidget 类的源文件主要代码在dropEvent函数中,当然首先需要在构造函数中开启接收拖拽事件的标识通过setAcceptDrops(true),来标识本窗口接收拖拽事件;

event->acceptProposedAction();

在dragEnterEvent函数中确认接受拖拽事件的动作,这样拖拽事件才能进入dropEvent函数;

   const QMimeData *mimedata= event->mimeData();

在dropEvent函数中直接通过QDropEvent 即可获取拖拽事件传递来的QMimeData 对象;

    if(mimedata->hasFormat("localtype"))

首先对传递来的QMimeData 对象进行类型判断,使用hasFormat函数,这里的类型参数即为拖拽事件产生窗口中设置的参数;

        QByteArray mimestr=mimedata->data("localtype");
        std::string sstr=mimestr.toStdString();

首先根据类型从QMimeData 对象中获取QByteArray 格式的数据,然后通过转换,恢复为原始类型,这里传递的是字符串类型,最终恢复为字符串类型;

        QLabel *label=new QLabel(this);
        QStyle *style = QApplication::style();
        QStyleOption option;
        QIcon icon = style->standardIcon(QStyle::SP_DialogOpenButton, &option, nullptr);
        QPixmap pixmap = icon.pixmap(32, 32);
        label->setPixmap(pixmap);
        label->move(event->pos());
        label->show();

后面为了拖拽事件更有趣味,在窗口中用Qlabel显示了许多图标。
main.cpp

#include <QApplication>

#include "dragdropwidget.h"
#include "acceptwidget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    DragDropWidget w;
    w.show();
    AcceptWidget aw;
    aw.move(800,0);
    aw.show();

    return a.exec();
}

demo.pro


QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = DragDropDemo
TEMPLATE = app

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
        main.cpp \
        dragdropwidget.cpp \
    acceptwidget.cpp

HEADERS += \
        dragdropwidget.h \
    acceptwidget.h

MOC_DIR = ./moc
OBJECTS_DIR = ./moc

Qt鼠标事件代码详解Qt是一个跨平台的应用程序开发框架,可以使用C++编写,并提供了丰富的图形界面和事件处理功能。鼠标事件Qt中常用的事件之一,用于处理与鼠标相关的操作。 在Qt中,鼠标事件可以分为三个主要的事件类别:鼠标按下事件、鼠标释放事件和鼠标移动事件。 鼠标按下事件(QMouseEvent::MouseButtonPress)是在鼠标按下按钮时触发的事件。可以通过重写QWidget或QGraphicsView的鼠标按下事件函数来处理。在该函数中,可以通过QMouseEvent对象获取鼠标的位置、按钮和修改键等信息,从而实现对鼠标按下事件的处理。 鼠标释放事件(QMouseEvent::MouseButtonRelease)是在鼠标释放按钮时触发的事件。与鼠标按下事件类似,可以通过重写相应的函数来处理,通过QMouseEvent对象获取相关信息。 鼠标移动事件(QMouseEvent::MouseMove)是在鼠标移动时触发的事件。可以通过重写QWidget或QGraphicsView的鼠标移动事件函数来处理。在该函数中,可以通过QMouseEvent对象获取鼠标的位置、按钮和修改键等信息,实现对鼠标移动事件的处理。 除了以上三类事件外,还有其他一些鼠标事件,如鼠标双击事件、鼠标进入事件、鼠标离开事件等。 处理鼠标事件有两种方式:重写QWidget或QGraphicsView的鼠标事件函数,或者使用事件过滤器来处理。使用事件过滤器可以在不修改源码的情况下,为特定的控件添加鼠标事件处理。 通过对鼠标事件的处理,可以实现各种鼠标交互功能,如点击按钮、拖拽操作、绘图等。在处理鼠标事件时,可以根据具体需求,提取并利用事件中的信息,实现相应的逻辑和效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值