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_OBJECTpublic: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 guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = DragDropDemo
TEMPLATE = appDEFINES += QT_DEPRECATED_WARNINGSSOURCES += \main.cpp \dragdropwidget.cpp \acceptwidget.cppHEADERS += \dragdropwidget.h \acceptwidget.hMOC_DIR = ./moc
OBJECTS_DIR = ./moc相关文章:
Qt拖拽事件详解及代码实现
Qt拖拽事件详解及代码实现 前言项目描述代码结构简介代码详解 前言 qt拖拽事件是一项非常常用并且非常好用的功能,拖拽实际上是一种信息传递的载体,其目的是将信息从一个对象传递给另一个对象。通过拖拽可以简化文件打开或业务操作流程,qt初…...
云原生的候选应用
提示 该内容摘自电子书《为 Azure 构建云原生 .NET 应用程序》,可在**.NET Docs**上获取,也可以免费下载 PDF并离线阅读。 考虑一下您的组织需要构建哪些应用程序。然后,看看您投资组合中的现有应用程序。其中有多少需要云原生架构ÿ…...
什么是单例模式?
单例模式是一种常见的设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个唯一实例。这种模式通常在需要控制某些资源的访问权限或确保对象的唯一性时使用。 单例模式的特点 唯一实例:单例模式确保一个类只有一个实例存在,全局可访问。 延迟实例化:在需…...
F4Pan百度网盘不限速直链解析工具最新可用
最新可用百度网盘不限速直链解析工具,现在很多解析网站和浏览器扩展都失效了,这个是用《F4Pan网盘解析系统开源源码》搭建的,有兴趣可以去研究研究。 下面看一下测试速度超过70MB每秒比开通会员还快非常的恐怖。 使用方法 1.下载F4Pan解析工…...
设计模式实战:智能家居系统的设计与实现
问题描述 设计一个智能家居系统,支持设备的控制(如灯、空调等),提供多种操作策略,并且在设备状态发生变化时通知用户。系统需要确保设备操作的灵活性和可扩展性。 设计分析 命令模式 命令模式用于将请求封装成对象,从而使我们可以用不同的请求、队列或日志来参数化其…...
Unity Rigidbody 踩坑记录
1:两个带有刚体的物体碰撞会一直不停的弹 把被动受力的刚提的 Freeze Position 的勾选 去掉(碰到过一次,有一种受力无法释放又返回给目标的 所以一直弹跳的感觉) 2:子物体 和父物体 都有刚体的情况下 子物体 Freeze R…...
Guitar Pro简谱怎么输入 ?如何把简谱设置到六线谱的下面?
一、Guitar Pro简谱怎么输入 简谱在音乐学习、演奏、创作和传播中都起着非常重要的作用,是音乐领域不可或缺的工具。吉他乐谱的制作可以使简谱,也可以使五线谱、六线谱等多种形式,这几种乐谱都可以使用Guitar Pro来完成。下面来看看Guitar Pr…...
Python 爬虫项目实战(一):爬取某云热歌榜歌曲
前言 网络爬虫(Web Crawler),也称为网页蜘蛛(Web Spider)或网页机器人(Web Bot),是一种按照既定规则自动浏览网络并提取信息的程序。爬虫的主要用途包括数据采集、网络索引、内容抓…...
Mongodb权限
MongoDB 的权限管理用于确保数据库的安全性并限制用户访问敏感数据。MongoDB 使用基于角色的访问控制(RBAC)来管理权限,允许管理员定义用户和角色,并为这些角色分配相应的权限。 Mongodb的内置角色 数据库角色 角色说明权限read…...
力扣第五十三题——最大子数组和
内容介绍 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组 是数组中的一个连续部分。 示例 1: 输入:nums [-2,1,-3,4,-1,2,1,-5,4] 输出&…...
达梦数据库:select报错:不是 GROUP BY 表达式
目录 SQL示例报错信息原因排查解决方法一:达梦支持灵活的处理方式,可以直接在查询中加hint参数方法二:修改dm.ini参数GROUP_OPT_FLAG1,动态,会话级参数,不用重启数据库方法三:配置兼容参数&…...
大模型卷向「下半场」,产业场景成拼杀重地
在19世纪的一个雨声潺潺的夏日,诗人拜伦与雪莱在瑞士的湖畔边闲聊,他们聊到了一个大胆的想法:如果能够把一个生物的各个部分制造出来,再组装到一起,赋予它生命的温暖,那会怎样? 这次对话激发了…...
OD C卷 - 多线段数据压缩
多段 线 数据压缩 (200) 如图中每个方格为一个像素(i,j),线的走向只能水平、垂直、倾斜45度;图中线段表示为(2, 8)、(3,7)、(3, 6)、(…...
密码学基础:搞懂Hash函数SHA1、SHA-2、SHA3(2)
目录 1.引入 2. SHA512-224\256 3.SHA-3 4.MD5 5.SM3 1.引入 上篇密码学基础:搞懂Hash函数SHA1、SHA-2、SHA3(1)-CSDN博客,我们先就将基础的SHA1\2讲解了,接下来我们继续聊SHA-3、SHA2变体SHA512_224\256等 2. SHA512-224\256 SHA512…...
C++ 异步编程:std::async、std::future、std::packaged_task 和 std::promise
C 异步编程:std::async、std::future、std::packaged_task 和 std::promise 在现代 C 编程中,异步编程已经成为一种常见的模式。利用 C11 引入的标准库组件 std::async、std::future、std::packaged_task 和 std::promise,我们可以更方便地处…...
OD C卷 - 石头剪刀布游戏
石头剪刀布游戏 (100) 剪刀石头布游戏,A-石头、B-剪刀、C-布游戏规则: 胜负规则,A>B; B>C; C>A;当本场次中有且仅有一种出拳形状优于其他出拳形状,则该形状的玩家是胜利者,否则认为是…...
关于k8s集群中kubectl的陈述式资源管理
1、k8s集群资源管理方式分类 (1)陈述式资源管理方式:增删查比较方便,但是改非常不方便 使用一条kubectl命令和参数选项来实现资源对象管理操作 (2)声明式资源管理方式:yaml文件管理 使用yam…...
XML 学习笔记
简介: (1)XML:可扩展性标记语言,用于传输和存储数据,而不是展示数据,是W3C 推举的数据传输格式。 XML的标签必须自定义,但是在写标签名的时候一定要有含义。 XML 只能有一个根节点…...
MongoDB未授权访问漏洞
2.MongoDB未授权访问漏洞 mongodb数据库是由C编写,主要是为了提供web应可用扩展的一种高性能数据库。开启MongoDB服务时不添加任何参数时,默认是没有权限验证的,登录的用户可以通过默认端口无需密码对数据库任意操作(增、删、改、查高危动作)而且可以远程访问数据库…...
数据安全、信息安全、网络安全区别与联系
关键字: 信息安全 数据安全 网络安全 [导读] 让人更好理解 “数据安全”、“信息安全”、“网络安全” 三者间的区别与联系了,我们汇总了官方机构给这三者的定义,并且网友也给出了自己的看法,一起来看看。 在 “互联网 ” 被广…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
