Qt拖放文件实现(Drag,Drop, MimeData )

1 背景

本文讲述了基于Qt实现文件拖放操作。拖放操作至少需要两个窗口,一个作为拖放源窗口,另一个作为拖放目标窗口。

2 实现

这里从QTreeView派生一个类TreeView,处理鼠标开始拖放操作及拖放事件。这个类既是拖放源窗口也是拖放目标窗口。

2.1 TreeView定义

TreeView定义如下:

class TreeView : public QTreeView
{Q_OBJECT
public:TreeView(QWidget *parent = nullptr);signals:void prepareDrag(QPoint const& point);void dragEnter(QDragEnterEvent * event);void dragMove(QDragMoveEvent * event);void drop(QDropEvent * event);protected:void mousePressEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent *event);void mouseReleaseEvent(QMouseEvent *event);void dragEnterEvent(QDragEnterEvent * event);void dragMoveEvent(QDragMoveEvent * event);void dropEvent(QDropEvent * event);
private:QPoint pressPoint;bool mousePress;bool isDrag;
};

说明:

  • 信号prepareDrag是开始拖放信号,这时TreeView是拖放源窗口。
  • 信号dragEnter是TreeView做为拖放目标窗口,有拖放进入该窗口时发送的信号。
  • 信号dragMove是TreeView做为拖放目标窗口,有拖放在该窗口移动时发送的信号。
  • 信号drop是TreeView做为拖放目标窗口,有拖放在该窗口完成拖放时发送的信号。
  • 重载函数mousePressEvent,mouseMoveEvent和mouseReleaseEvent处理鼠标事件,发送开拖放信号。
  • 重载函数dragEnterEvent,dragMoveEvent和dropEvent处理拖放事件。

2.2 TreeView实现

2.2.1 构造函数

TreeView::TreeView(QWidget *parent): QTreeView(parent), mousePress(false), isDrag(false)
{setMouseTracking(true);setAcceptDrops(true);
}

说明:

  • 通过setMouseTracking将鼠标设置为可跟踪的,以便处理鼠标移动操作。
  • 通过setAcceptDrops将对象设置为拖放目标窗口。

2.2.2 鼠标事件

void TreeView::mousePressEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){pressPoint = event->pos();mousePress = true;}QTreeView::mousePressEvent(event);
}void TreeView::mouseMoveEvent(QMouseEvent *event)
{if(mousePress){int distance = (event->pos() - pressPoint).manhattanLength();if(distance >= QApplication::startDragDistance()){mousePress = false;emit prepareDrag(pressPoint);}isDrag = true;}if(isDrag)return;QTreeView::mouseMoveEvent(event);
}void TreeView::mouseReleaseEvent(QMouseEvent *event)
{mousePress = false;isDrag = false;QTreeView::mouseReleaseEvent(event);
}

说明:

  • 在鼠标按下事件中,记下按下时鼠标位置pressPoint.
  • 在鼠标移动事件中,根据移动距离判断是否是启动拖放操作。
  • 是拖放操作设置isDrag为true。
  • 在鼠标释放事件中,恢复状态。

2.2.3 拖放事件

void TreeView::dragEnterEvent(QDragEnterEvent * event)
{emit dragEnter(event);
}void TreeView::dragMoveEvent(QDragMoveEvent * event)
{emit dragMove(event);
}void TreeView::dropEvent(QDropEvent * event)
{emit drop(event);
}

说明:拖放事件处理很简单,分别发送对应的信号。

3 使用

从QWidget派生一个类型Widget.

3.1 Widget 定义

Widget 定义如下:

class Widget : public QWidget
{Q_OBJECT
public:Widget(QWidget *parent = nullptr);~Widget();private slots:void beginDrag(QPoint const& point);void dragEnter(QDragEnterEvent * event);void dragMove(QDragMoveEvent * event);void drop(QDropEvent * event);
private:Ui::Widget *ui;
};

3.2 Widget实现

下面分别讲述一下构造函数,beginDrag,dragEnter,dragMove和drop的实现.

3.2.1 构造函数

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(ui->treeview, SIGNAL(prepareDrag(QPoint)),this, SLOT(beginDrag(QPoint)));connect(ui->treeview, SIGNAL(dragEnter(QDragEnterEvent*)),this, SLOT(dragEnter(QDragEnterEvent*)));connect(ui->treeview, SIGNAL(dragMove(QDragMoveEvent*)),this, SLOT(dragMove(QDragMoveEvent*)));connect(ui->treeview, SIGNAL(drop(QDropEvent*)),this, SLOT(drop(QDropEvent*)));
}

该函数将对象TreeView的4个信号与Widget对应的槽函数连接起来。

3.2.2 beginDrag

#define FILE_URL_HEADER "file:///"
void Widget::beginDrag(QPoint const& point)
{QModelIndex index = ui->treeview->indexAt(point);if(!index.isValid())return;QStringList fileNames;if(index.row() % 2)fileNames = QStringList() << FILE_URL_HEADER + "D:/file1.txt";elsefileNames = QStringList() << FILE_URL_HEADER + "D:/file1.txt" << FILE_URL_HEADER + "D:/file2.txt";QString text = fileNames.join("\n");if(fileNames.size() > 1)text += "\n";QDrag *drag = new QDrag(ui->treeview);QMimeData* mineData = new QMimeData();mineData->setData("text/uri-list", text.toUtf8());drag->setMimeData(mimeData);drag->setPixmap(QPixmap(":/image/copy.png"));drag->exec(Qt::LinkAction | Qt::MoveAction | Qt::CopyAction , Qt::CopyAction);
}

函数流程:

  • 根据point获取鼠标是否选择对象,如果选中对象开始拖放,否则不拖放。
  • 构造文件名数组,注意文件名以file:///为前缀。
  • 以ui->treeview为参数创建拖放对象drag。
  • 创建QMimeData对象mineData,通过setData将文件名设置给类型text/uri-list。
  • 以mineData为参数来设置drag的MimeData。
  • 设置drag的Pixmap作为拖放时图标显示。
  • 开始进入拖放状态,默认拖放动作是Copy。同时也支持Link和Move拖放动作。

3.2.3 dragEnter

void Widget::dragEnter(QDragEnterEvent* event)
{QMimeData const* mimeData = event->mimeData();if(mimeData)event->acceptProposedAction();elseevent->ignore()
}

该函数是拖放状态下鼠标进入窗口时调用。可以有如下选择:

  • 择接受拖放请求,这时拖放图标显示为鼠标箭头+复制图标
  • 不接受拖放请求调用,这时拖放图标显示为红色禁止+复制图标。

3.2.4 dragMove

void Widget::dragMove(QDropEvent* event)
{QModelIndex index = ui->treeview->indexAt(event->pos());bool isSelf = (event->source() == ui->treeview);if(index.isValid()){if(isSelf && (index.row() % 2))event->ignore();elseevent->acceptProposedAction();}else{if(isSelf)event->ignore();elseevent->acceptProposedAction();}
}

该函数是拖放状态下鼠标在窗口中移动时调用。可以根据实际应用需要选择接受还是拒绝拖放请求。

3.2.5 drop

void Widget::drop(QDropEvent* event)
{QMimeData const* mimeData = event->mimeData();if(!mimeData)return;QString text = mimeData->text().remove(FILE_URL_HEADER);if(text.endsWith("\n"))text.remove(text.size() - 1, 1);QStringList fileNames = text.split("\n");if(event->dropAction() == Qt::MoveAction){// move files}else if(event->dropAction() == Qt::CopyAction){// copy files}else if(event->dropAction() == Qt::LinkAction){// create shortcuts}
}

该函数是拖放状态下并且接受拖放请求,鼠标释放时调用函数。
函数流程:

  • 从mimeData中获取文件名。
  • 根据拖放动作执行对应的操作。
    说明:默认是Copy动作,在拖放状态下按Alt或Alt+Shift键可以切换支持的拖放动作。

4 总结

本文讲述了Qt下文件拖放操作,其实不只是文件操作,其它操作也是可以,只需给给mineData设置对应对象就可以。另外本文描述文件拖放操作,只是自己程序内部拖放操作。与文件资源管理器相互拖放还需要给mineData设置其它格式对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/762413.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自上而下的角色扮演游戏资产包幻想梦境

Fantasy Dreamland 是一個完整的資源包,包含開始製作自上而下的像素藝術遊戲所需的一切! 幻想夢境瓷磚套裝: - 超過 13,000 塊瓷磚! - 超過 500 個動畫圖塊! - 鐵匠! - 城堡! - 洞穴! - 聖誕節! (裝飾) - 城市! - 沙漠! - 沙漠房屋! - 夢想/天空! - …

【解决】使用Jekyll框架进入网页终端返回找不到.min.js或者类似Rollup模块化构建js失败问题

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 文章目录 一、问题表现二、问题解决&#xff08;一&#xff09;检查输出目录&#xff08;二&#xff09;启动Rollup构建 三、…

PCD1000AE单通道高压线性恒流LED控制芯片

概述 PCD1000AE 是一款线性恒流 IC&#xff0c;输出电流可调&#xff0c;恒流精度高&#xff0c;应用方案简单&#xff0c;成本和阻容降压相当&#xff0c;具有过温保护功能&#xff0c;更安全&#xff0c;更可靠。 特点 输出电流可调 5mA-60mA&#xff0c; 恒流精度可以达…

【C++】vector容器初步模拟

送给大家一句话&#xff1a; 努力一点&#xff0c;漂亮—点&#xff0c;阳光一点。早晚有一天&#xff0c;你会惊艳了时光&#xff0c;既无人能替&#xff0c;又光芒万丈。 vector容器初步模拟 1 认识vector开始了解底层实现 2 开始实现成员变量构造函数 析构函数尾插迭代器插入…

【漏洞复现】福建科立迅通信指挥调度平台down_file.php sql注入漏洞

漏洞描述 福建科立迅通信调度平台 20240318 以及之前版本存在一个严重漏洞,影响了文件 api/client/down_file.php 的一个未知功能。攻击者可以通过操纵参数 uuid 发起 SQL 注入攻击。攻击者可以远程发起攻击。 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守…

GraalVM详细安装及打包springboot、java、javafx使用教程(打包springboot2篇)

前言 在当前多元化开发环境下&#xff0c;Java作为一种广泛应用的编程语言&#xff0c;其应用部署效率与灵活性的重要性日益凸显。Spring Boot框架以其简洁的配置和强大的功能深受开发者喜爱&#xff0c;而JavaFX则为开发者提供了构建丰富桌面客户端应用的能力。然而&#xff…

基于Java中的SSM框架实现图书仓储管理系统项目【项目源码+论文说明】

基于Java中的SSM框架实现图书仓储管理系统演示 摘要 随着社会经济的迅速发展和科学技术的全面进步&#xff0c;计算机事业的飞速发展&#xff0c;以计算机与通信技术为基础的信息系统正处于蓬勃发展的时期&#xff0c;随着经济文化水平的显著提高&#xff0c;人们对生活质量及…

3.idea的import和open的区别

1.推荐open的情况&#xff1a;如果项目里面有.idea,推荐Open打开。 2.推荐import的情况&#xff1a;如果项目里面没有.idea,推荐import打开。但是新版idea改了import的地方&#xff0c;在File—>New—>Select directory with existing sources。 3.导入项目的情况&#x…

【视频图像取证篇】模糊图像增强技术之锐化类滤波场景应用小结

【视频图像取证篇】模糊图像增强技术之锐化类滤波场景应用小结 模糊图像增强技术之锐化类滤波场景应用小结—【蘇小沐】 &#xff08;一&#xff09;锐化类滤波器 模糊消除类滤波器&#xff08;Remove blur / Unsharpness&#xff09;。 通用去模糊滤波器&#xff1a;针对大…

(ROOT)KAFKA详解

生产篇 使用 /** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to Y…

#Linux(环境变量)

&#xff08;一&#xff09;发行版&#xff1a;Ubuntu16.04.7 &#xff08;二&#xff09;记录&#xff1a; &#xff08;1&#xff09;查看环境变量 &#xff08;2&#xff09;修改环境变量 第一种方法&#xff1a;直接使用命令设置&#xff08;立即生效&#xff0c;只会作用…

了解交换机上的SFP和QSFP端口

在当今互联的世界中&#xff0c;可靠、高效的网络通信对于企业的蓬勃发展至关重要。为了实现顺畅的连接&#xff0c;了解能够实现该目标的技术非常重要。其中一项关键技术是交换机上的SFP和QSFP端口。本文将简要介绍这些概念&#xff0c;定义并解释交换机SFP端口和QSFP端口的优…

50道JAVA基础算法编程题【内含分析、程序答案】

【程序1】 题目&#xff1a;古典问题&#xff1a;有一对兔子&#xff0c;从出生后第3个月起每个月都生一对兔子&#xff0c;小兔子长到第三个月后每个月又生一对兔子&#xff0c;假如兔子都不死&#xff0c;问每个月的兔子总数为多少&#xff1f; 程序分析&#xff1a; 兔子的…

视频私有云,HDMI/AV多硬件设备终端接入,SFU/MCU视频会议交互方案。

在视频业务深入的过程中越来越多的硬件设备接入视频交互的视频会议中远程交互&#xff0c;有的是视频采集&#xff0c;有的是医疗影像等资料&#xff0c;都需要在终端承显&#xff0c;这就需要我们的设备终端能多设备&#xff0c;多协议接入&#xff0c;设备接入如下。 1&#…

【Python操作基础】系列——赋值语句

&#x1f349;CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一&#xff5c;统计学&#xff5c;干货分享          擅长Python、Matlab、R等主流编程软件          累计十余项国家级比赛奖项&#xff0c;参与研究经费10w、40w级横向 文…

Flutter Dart BigDecimal

目录 前言API构造函数四则及幂运算其他 代码BigDecimal.dartbigdecimal_test.dart 前言 Dart中只有BigInt没有BigDecimal&#xff0c;所以需要手动去实现BigDecimal。 如果我的代码帮到你&#xff0c;请给我点个赞。 API 构造函数 BigDecimal([dynamic number]) 将任意toSt…

软件应用,宠物医院兽医开的处方单管理系统软件教程,宠物店营业软件教程

软件应用&#xff0c;宠物医院兽医开的处方单管理系统软件教程&#xff0c;宠物店营业软件教程 一、前言 以下软件操作教程以 佳易王宠物医院兽医处方软件V17.0为例说明 件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 在开处方单的时候&#xff0c;可以打…

工程信号的去噪和(分类、回归和时序)预测

&#x1f680;【信号去噪及预测论文代码指导】&#x1f680; 还为小论文没有思路烦恼么&#xff1f;本人专注于最前沿的信号处理与预测技术——基于信号模态分解的去噪算法和深度学习的信号&#xff08;回归、时序和分类&#xff09;预测算法&#xff0c;致力于为您提供最精确、…

硬核分享|免费快速的高保真图片压缩方案

硬核分享|免费快速的高保真图片压缩方案_哔哩哔哩_bilibili 在当今数字化时代&#xff0c;图像已然成为我们日常生活中必不可少的元素之一。但是&#xff0c;伴随着高清相机与日俱增以及拍摄照片数量的飞速增长&#xff0c;如何安全、高效的存储和传播海量图片已逐渐成为亟待解…

【NLP6-使用seq2seq模型架构实现英译法任务】

使用seq2seq模型架构实现英译法任务 目标 1、更深一步了解seq2seq模型架构和翻译数据集 2、掌握适用基于GRU的seq2seq模型实现翻译过程 3、掌握Attention机制在解码器端的实现过程 seq2seq模型架构 encoder编码器 Decoder解码器 数据预览 基于GRU的seq2seq模型架构实现…