qt中的拖拽及其使用技巧
关于qt中的拖放操作,首先可以看这篇官方文档:http://doc.qt.io/qt-5.5/dnd.html
一、QDrag
首先是创建QDrag,可以在mousePressEvent或者mouseMoveEvent中创建。
void DragDropWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
QDrag *drag = new QDrag(this);
QMimeData *data = new QMimeData;
drag->setMimeData(data);
drag->exec(Qt::MoveAction);
}
}
或者
void DragDropWidget::mousePressEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton)
{
startPos = event->pos();
}
}
void DragDropWidget::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton)
{
if ((event->pos() - startPos).manhattanLength() < QApplication::startDragDistance())
{
QDrag *drag = new QDrag(this);
QMimeData *data = new QMimeData;
drag->setMimeData(data);
drag->exec(Qt::LinkAction);
}
}
}
QDrag在exec前,一定要设置QMimeData,否则会弹出警告“QDrag: No mimedata set before starting the drag”。并且不会开始拖拽操作。
QMimeData在拖拽中非常有用,可以用来保存拖拽操作附带的信息,比如字符串、文件或者图片,同时也可以用来验证其所保存的信息格式,并以此来判断是否可接收。未来再补充QMimeData的用法。
另外要注意,在windows下,QDrag::exec()是个同步操作,要在exec()返回后,才会继续执行下面的代码。
二、drag相关事件
首先,当需要一个控件接收drag和drop,就要先调用控件的方法:setAcceptDrops(true)。
qt中一共有三个drag相关事件,dragEnterEvent、dragMoveEvent、dragLeaveEvent。这三个事件触发条件类似鼠标移入,鼠标移动,鼠标移出。当鼠标拖拽进入控件触发dragEnterEvent,在控件内拖拽移动触发dragMoveEvent,鼠标拖拽离开控件触发dragLeaveEvent。
dragEnterEvent事件有一个参数,参数类型是QDragEnterEvent,继承自QDragMoveEvent。
dragMoveEvent事件有一个参数,参数类型是QDragMoveEvent。
dragLeaveEvent事件有一个参数,参数类型是QDragLeaveEvent,继承自QEvent,无特别用法。
当鼠标拖拽进入控件时,会触发dragEnterEvent,如果不做处理,后续将不会接收到dragMoveEvent事件和dragLeaveEvent事件。在dragEnterEvent事件中,如果调用了QDragMoveEvent::accept()函数,后续将可以收到dragMoveEvent事件和dragLeaveEvent事件。而如果调用QDragMoveEvent::ignore()函数,效果相当于不处理,不会接收后续事件。
void DragDropWidget::dragEnterEvent(QDragEnterEvent *event)
{
if (event->source() == this)
event->ignore();
else
event->accept();
}
发起drag的控件自身也是可以接受到来自自身的drag的相关事件的,这个要注意,处理不好容易出bug。
三、dropEvent
当drag为accept状态,然后释放鼠标,就会产生dropEvent。我们可以在这个事件里处理本次拖拽附带的Mime信息。
四、使用技巧
在我的一个项目中,需要通过拖拽操作连接两个控件,然后在两个控件之间画连接线。这里有两种控件,画布控件CanvasWidget,和节点控件NodeWidget。NodeWidget在CanvasWidget上,连接线也是在CanvasWidget上绘制。我们可以在NodeWidget的dropEvent事件里给CanvasWidget发送连接信号,告诉CanvasWidget两个NodeWidget已经相连了。
void NodeWidget::dropEvent(QDropEvent *event)
{
auto src = event->source();
event->setDropAction(Qt::LinkAction);
event->accept();
emit linked(src, this);
}
然后我又想在拖拽的过程中就看到一条动态的连接线,这时候就要用到CanvasWidget的drag相关事件。在CanvasWidget的dragMoveEvent事件中这样处理:
void CanvasWidget::dragMoveEvent(QDragMoveEvent *event)
{
m_lineDraging.end = event->pos();
update();
}
m_lineDraging就是用来绘制的动态连接线。设置完连接线的端点,然后再update()一下,就可以显示了。当然这只是一个简单方案,还没有验证过在绘制量较大时,在move事件中update会不会很卡。
下面是效果图
Qt Drag and Drop思维导图
参考资料:
- http://doc.qt.io/qt-5.5/dnd.html
- http://blog.csdn.net/pcsuite/article/details/6147191
qt中的拖拽及其使用技巧的更多相关文章
- [Qt]Qt中TreeWidget拖拽事件
文章在简书里啦 http://www.jianshu.com/p/45b740060aca
- Asp.net中存储过程拖拽至dbml文件中,提示无法获得返回值
Asp.net中存储过程拖拽至dbml文件中,提示无法获得返回值,去属性表中设置这时候会提示你去属性表中更改返回类型. 其实存储过程返回的也是一张表,只不过有时候存储过程有点复杂或者写法不规范的话不能 ...
- iOS开发拓展篇—xib中关于拖拽手势的潜在错误
iOS开发拓展篇—xib中关于拖拽手势的潜在错误 一.错误说明 自定义一个用来封装工具条的类 搭建xib,并添加一个拖拽的手势. 主控制器的代码:加载工具条 封装工具条以及手势拖拽的监听事件 此时运行 ...
- iOS - xib中关于拖拽手势的潜在错误
iOS开发拓展篇—xib中关于拖拽手势的潜在错误 一.错误说明 自定义一个用来封装工具条的类 搭建xib,并添加一个拖拽的手势. 主控制器的代码:加载工具条 封装工具条以及手势拖拽的监听事件 此时运行 ...
- QT之——QTableWidget拖拽单元格并替换内容(进阶)
所需待重写函数: [virtual] bool QObject::eventFilter(QObject *watched, QEvent *event); /* * Filters events i ...
- H5中的拖拽事件
最近浏览了张鑫旭大神的基于HTML5 drag/drop模块拖动插入排序删除完整实例,感觉受益匪浅.于是将最做的demo记录下来. 首先浏览一下事件,这些事件比较好记,只要记住用在谁的身上就好了,无非 ...
- Android中GridView拖拽的效果【android进化三十六】
最 近看到联想,摩托罗拉等,手机launcher中有个效果,进入mainmenu后,里面的应用程序的图标可以拖来拖去,所以我也参照网上给的代码,写了 一个例子.还是很有趣的,实现的流畅度没有人家的 ...
- Android中GridView拖拽的效果
最 近看到联想,摩托罗拉等,手机launcher中有个效果,进入mainmenu后,里面的应用程序的图标可以拖来拖去,所以我也参照网上给的代码,写了 一个例子.还是很有趣的,实现的流畅度没有人家的那么 ...
- 浅谈DevExpress<四>:TreeList中的拖拽功能
本篇要实现的目标,简单来说就是把一个treelist的节点用鼠标拖到另外的节点(自身或其他的listview)上,如下图: 1
随机推荐
- HDU - 1005 Number Sequence (矩阵快速幂)
A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mo ...
- VIM 用正则表达式,非贪婪匹配,匹配竖杠,竖线, 匹配中文,中文正则,倒数第二列, 匹配任意一个字符 :
VIM 用正则表达式 批量替换文本,多行删除,复制,移动 在VIM中 用正则表达式 批量替换文本,多行删除,复制,移动 :n1,n2 m n3 移动n1-n2行(包括n1,n2)到n3行之下: ...
- Cisco DNA-C POC环境配置
Step1:在DNA-C上创建Site,本例创建Global->China->WangJiang->20 F如下图: Step2:配置fusion区域的AAA和NTP等信息,如下图: ...
- 【Linux】Ubuntu16.04 ftp匿名访问
一.安装: 1.安装命令: sudo apt-get install vsftpd 2.配置文件: vi /etc/vsftpd.conf 3.开启.关闭.重启服务 sudo /etc/init.d/ ...
- Python9_类
类的基础知识 属性:类变量.实例变量.方法:初始化方法 __init__ //初始化方法不是必须的:其他方法: //类的定义class Employee: empCount = 0 //类变量,有些 ...
- Ubuntu常用命令大全 以及 PHP+MySQL代码部署在Linux(Ubuntu)上注意事项
PHP+MySQL代码部署在Linux(Ubuntu)上注意事项 https://cloud.tencent.com/developer/article/1024187 Ubuntu常用命令大全 ht ...
- C++版本的UnEscape 解析\uxxxx\uxxxx编码字符
解析类似于这种Unicode编码格式的字符串 \u5b55\u5987\u88c5\u590f\u88c52018\u65b0\u6b3e\u5bbd\u677e\u77ed\u8896\u4e2d\ ...
- $SP$3267 $DQUERY - D-query$ 主席树
正解:主席树 解题报告: 传送门! 一直在做$dp$题好久没做做别的了,,,所以来做点儿别的练练手,,,不然以前学的全忘了要/$kk$ 然后这题好像可以莫队/主席树/线段树/树状数组? 我就先只港下主 ...
- SingletonPattern(单例模式)-----Java/.Net
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一. 这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创建自己的 ...
- python中的enumerate、map、filter和zip函数
引入 python内置了很多可以供我们直接调用的函数,这些函数的效率往往都非常高.我们在自己造轮子的同时,也非常有必要了解并且正确使用python给我们提供的大量的内置函数.在前面的博客里面我已经介绍 ...