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服务时不添加任何参数时,默认是没有权限验证的,登录的用户可以通过默认端口无需密码对数据库任意操作(增、删、改、查高危动作)而且可以远程访问数据库…...
数据安全、信息安全、网络安全区别与联系
关键字: 信息安全 数据安全 网络安全 [导读] 让人更好理解 “数据安全”、“信息安全”、“网络安全” 三者间的区别与联系了,我们汇总了官方机构给这三者的定义,并且网友也给出了自己的看法,一起来看看。 在 “互联网 ” 被广…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
