拖放 Drag and Drop,有时又被称为 DnD,是现代软件开发中必不可少的一项技术。它提供了一种能够在应用程序内部甚至是应用程序之间进行信息交换的机制,并且,操作系统与应用程序之间进行剪贴板的内容交换,也可以被认为是 DnD 的一部分。
DnD 其实是由两部分组成的:Drag 和 Drop。Drag 是将被拖放对象“拖动”,Drop 是将被拖放对象“放下”,前者一般是一个按下鼠标的过程,而后者则是一个松开鼠标的过程,这两者之间鼠标一直是被按下的。当然,这只是一种通常的情况,其他情况还是要看应用程序的具体实现。对于 Qt 而言,widget既可以作为 drag 对象,也可以作为 drop 对象,或者二者都是。
下面的一个例子来自 C++ GUI Programming with Qt 4, 2nd Edition。在这个例子中,我们创建一个程序,可以将系统中的文本文件拖放过来,然后在窗口中读取内容。
mainwindow.h
  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QtGui>
  4. class MainWindow : public QMainWindow
  5. {
  6. Q_OBJECT
  7. public:
  8. MainWindow(QWidget *parent = 0);
  9. ~MainWindow();
  10. protected:
  11. void dragEnterEvent(QDragEnterEvent *event);
  12. void dropEvent(QDropEvent *event);
  13. private:
  14. bool readFile(const QString &fileName);
  15. QTextEdit *textEdit;
  16. };
  17. #endif // MAINWINDOW_H
mainwindow.cpp
  1. #include "mainwindow.h"
  2. MainWindow::MainWindow(QWidget *parent)
  3. : QMainWindow(parent)
  4. {
  5. textEdit = new QTextEdit;
  6. setCentralWidget(textEdit);
  7. textEdit->setAcceptDrops(false);
  8. setAcceptDrops(true);
  9. setWindowTitle(tr("Text Editor"));
  10. }
  11. MainWindow::~MainWindow()
  12. {
  13. }
  14. void MainWindow::dragEnterEvent(QDragEnterEvent *event)
  15. {
  16. if (event->mimeData()->hasFormat("text/uri-list")) {
  17. event->acceptProposedAction();
  18. }
  19. }
  20. void MainWindow::dropEvent(QDropEvent *event)
  21. {
  22. QList<QUrl> urls = event->mimeData()->urls();
  23. if (urls.isEmpty()) {
  24. return;
  25. }
  26. QString fileName = urls.first().toLocalFile();
  27. if (fileName.isEmpty()) {
  28. return;
  29. }
  30. if (readFile(fileName)) {
  31. setWindowTitle(tr("%1 - %2").arg(fileName, tr("Drag File")));
  32. }
  33. }
  34. bool MainWindow::readFile(const QString &fileName)
  35. {
  36. bool r = false;
  37. QFile file(fileName);
  38. QTextStream in(&file);
  39. QString content;
  40. if(file.open(QIODevice::ReadOnly)) {
  41. in >> content;
  42. r = true;
  43. }
  44. textEdit->setText(content);
  45. return r;
  46. }
main.cpp
  1. #include <QtGui/QApplication>
  2. #include "mainwindow.h"
  3. int main(int argc, char *argv[])
  4. {
  5. QApplication a(argc, argv);
  6. MainWindow w;
  7. w.show();
  8. return a.exec();
  9. }
这里的代码并不是很复杂。在MainWindow中,一个QTextEdit作为窗口中间的widget。这个类中有两个protected的函数:dragEnterEvent() 和 dropEvent(),这两个函数都是继承自 QWidget,看它们的名字就知道这是两个事件,而不仅仅是signal。
在构造函数中,我们创建了 QTextEdit 的对象。默认情况下,QTextEdit 可以接受从其他的应用程序拖放过来的文本类型的信息。如果用户把一个文件拖到这里面,那么就会把文件名插入到文本的当前位置。但是我们希望让MainWindow 读取文件内容,而不仅仅是插入文件名,所以我们在MainWindow中对 drop 事件进行了处理,因此要把QTextEdit的setAcceptDrops()函数置为false,并且把MainWindow的setAcceptDrops()置为true,以便让MainWindow对 drop 事件进行处理。
当用户将对象拖动到组件上面时,dragEnterEvent()函数会被回调。如果我们在事件处理代码中调用 acceptProposeAction() 函数,我们就可以向用户暗示,你可以将拖动的对象放在这个组件上。默认情况下,组件是不会接受拖放的。如果我们调用了这样的函数,那么Qt会自动地以光标来提示用户是否可以将对象放在组件上。在这里,我们希望告诉用户,窗口可以接受拖放。因此,我们首先检查拖放的MIME类型。MIME类型为 text/uri-list 通常用来描述一个 URI 的列表。这些 URI 可以是文件名,可以是 URL或者其他的资源描述符。MIME类型由 Internet Assigned Numbers Authority (IANA) 定义,Qt 的拖放事件使用MIME类型来判断拖放对象的类型。关于 MIME类型的详细信息,请参考 http://www.iana.org/assignments/media-types/.
当用户将对象释放到组件上面时,dropEvent() 函数会被回调。我们使用 QMimeData::urls()来或者 QUrl 的一个list。通常,这种拖动应该只用一个文件,但是也不排除多个文件一起拖动。因此我们需要检查这个list是否为空,如果不为空,则取出第一个。如果不成立,则立即返回。最后我们调用 readFile() 函数读取文件内容。关于读取操作我们会在以后的章节中详细说明,这里不再赘述。
好了,至此我们的小程序就解释完毕了,运行一下看看效果吧!
对于拖动和脱离,Qt 也提供了类似的函数:dragMoveEvent() 和 dragLeaveEvent(),不过对于大部分应用而言,这两个函数的使用率要小得多。
本文转自 FinderCheng 51CTO博客,原文链接:http://blog.51cto.com/devbean/280052

Qt学习之路(52): 拖放技术之一相关推荐

  1. QT学习之路2 学习笔记

    QT学习之路2 学习笔记 1.Qt 是一个著名的 C++ 应用程序框架.你并不能说它只是一个 GUI 库,因为 Qt 十分庞大,并不仅仅是 GUI 组件.使用 Qt,在一定程度上你获得的是一个&quo ...

  2. 《Qt 学习之路 2》

    Home / Qt 学习之路 2 / <Qt 学习之路 2>目录 <Qt 学习之路 2>目录 序 Qt 前言 Hello, world! 信号槽 自定义信号槽 Qt 模块简介 ...

  3. java qt gui_工控编程,Qt 学习之路

    原标题:工控编程,Qt 学习之路 Qt 是一个著名的 C++ 库--或许并不能说这只是一个 GUI 库,因为 Qt 十分庞大,并不仅仅是 GUI.使用 Qt,在一定程序上你获得的是一个"一站 ...

  4. Qt学习之路(24): QPainter(改写paintEvent)

    Qt学习之路(24): QPainter(改写paintEvent) 多些大家对我的支持啊!有朋友也提出,前面的几节有关event的教程缺少例子.因为event比较难做例子,也就没有去写,只是把大概写 ...

  5. 转载: Qt 学习之路 2归档

    Qt 学习之路 2归档 http://www.devbean.net/2012/08/qt-study-road-2-catelog/

  6. 对QT学习之路12-14的源代码补充与修正

    QT学习之路12-14的源代码有些不完整,为了更好的让大家学习,本人做了一点修正与补充,谢谢.源代码如下: 头文件: #ifndef MAINWINDOW_H #define MAINWINDOW_H ...

  7. Qt学习之路_12(简易数据管理系统)

    原文地址为: Qt学习之路_12(简易数据管理系统) 前言 最近从大陆来到台湾,之间杂事很多,挤不出时间来更新博客- 这次主要是通过做一个简易的数据库管理系统,来学习在Qt中对数据库,xml,界面的各 ...

  8. QT学习之路(一)ubuntu 18.04的Qt Creator在线安装

    文章目录 前言 一.准备工作 二.安装步骤 参考链接 前言 Qt是嵌入式开发的必备工具之一,在Linux下安装尤其重要. Qt是C++的一个库,或者说是开发框架,里面集成了一些库函数,提高开发效率. ...

  9. [记录]学习QT学习之路2第四天

    今天学习内容对应<<QT学习之路2>>第18到23部分,主要是有关于QT事件这一部分的内容(=_=真是看到我快吐了,感觉这本书不适合我这种初学者). 先放出思维导图 难点总结 ...

最新文章

  1. 数据库开发基本操作-关于sql server 2005 未开放1433端口的问题
  2. python调用海康sdk 数据类型
  3. xenserver 脚本学习之/opt/xensource/bin/xapi-wait-init-complete
  4. C#隐藏桌面图标和任务栏
  5. 基于JAVA+SpringBoot+Mybatis+MYSQL的请假与审批系统
  6. Kubernetes集群部署1
  7. 服务器端可控情形的Javascript跨域访问解决方法
  8. intellij idea 在什么地方打开终端Terminal
  9. 【渝粤教育】国家开放大学2018年秋季 1131t卫生经济学 参考试题
  10. Mac和windows哪个好
  11. 线程的创建以及线程的本质
  12. ArcGIS 对DEM数据进行剖面分析
  13. 中国省市区列表MySQLl数据库脚本
  14. C#nameof用法
  15. 计算机更新配置卡住了,win10更新设置卡死怎么办|win10更新设置卡死的完美解决方法...
  16. 天翼云主攻“5G+云+AI”,新生态革命的冲锋
  17. 利用Flourish制作动态条形图
  18. 微信小程序开发(三)——IE盒子,Flex弹性布局,色子六面
  19. [海思]--Hi3516a--添加新Sensor
  20. 音频压缩工具——Speex的使用

热门文章

  1. 你遇到过哪些理工科的实验高手,他们有哪些优秀的思维习惯?
  2. LaTex文章中插入Visio及Matlab矢量图
  3. Stanford UFLDL教程 深度网络概览
  4. 编程之美-连连看游戏设计方法整理
  5. 编程之美-饮料供货方法整理
  6. 常用python模块
  7. swoole学习(一)----linux安装swoole
  8. Android热补丁之Robust(三)坑和解
  9. 部署awstats分析系统
  10. 基于Foursquare, 我们还能做什么 ?