Qt实例学习--事件处理和简单拖拽实现原理
来源:互联网 发布:德尔菲神谕 知乎 编辑:程序博客网 时间:2024/05/21 07:55
这是Qt的关于drag&paste主题的Demo的一个实例,我做了注解。效果图如下下面的部分是主要的实现的部分,从下面的例子可以看出,实现drag&drop功能,主要要做的事情就是重写几个event handler以及设计event的MIME数据类型。
#include #include "draglabel.h"#include "dragwidget.h"DragWidget::DragWidget(QWidget *parent) : QWidget(parent){ QFile dictionaryFile(":/dictionary/words.txt"); //此文件中存放了需要创建的所有的label的名字 dictionaryFile.open(QIODevice::ReadOnly); //打开文件 QTextStream inputStream(&dictionaryFile); int x = 5; int y = 5; while (!inputStream.atEnd()) { //对于打开文件中的每一个单词,都创建一个text label QString word; inputStream >> word; if (!word.isEmpty()) { DragLabel *wordLabel = new DragLabel(word, this); //在这里创建label wordLabel->move(x, y); //放置label到适当的位置 wordLabel->show(); wordLabel->setAttribute(Qt::WA_DeleteOnClose); //设置属性,当此widget被设置为非可见模式时,就删除它 x += wordLabel->width() + 2; if (x >= 195) { x = 5; y += wordLabel->height() + 2; } } } QPalette newPalette = palette(); newPalette.setColor(QPalette::Window, Qt::white); setPalette(newPalette); setAcceptDrops(true); //此处的设置很关键,允许释放在本widget上 setMinimumSize(400, qMax(200, y)); setWindowTitle(tr("Draggable Text"));}void DragWidget::dragEnterEvent(QDragEnterEvent *event) //这个handler是在拖拽进入到本widget的时候,是针对从程序外面拖拽到应用程序内的情况,在应用程序中拖动的情况,不适用这个handler{ if (event->mimeData()->hasText()) { if (children().contains(event->source())) { //判断拖动源是否是本widget的children widget.如果是的话,就执行移动操作 event->setDropAction(Qt::MoveAction); //此处的setDropAction()函数是否只是相当于设置了一个flag.此flag做为返回值被返回给调用的函数,用于判断event执行的是何种操作?? event->accept(); } else { //这种情况是当拖拽是从本应用程序以外的地方拖进来的话 event->acceptProposedAction(); } } else { event->ignore(); }}void DragWidget::dropEvent(QDropEvent *event) //当拖动的widget放下的时候,此事件被触发,此handler被调用{ if (event->mimeData()->hasText()) { //此条件过滤掉了一些比如拖拽图标啊,图片啊进来的情况,只允许拖拽文字进来 const QMimeData *mime = event->mimeData(); //取出伴随着event的MIME数据 QStringList pieces = mime->text().split(QRegExp("//s+"), QString::SkipEmptyParts); //有可能很多个词(比如一句话)被拖拽,那么根据空格来将多个词变为多个label QPoint position = event->pos(); //这个point很明显是widget被放下时的point.因为这是在dropEvent中 QPoint hotSpot; //hotSpot是拖拽开始时的point.注意,hotSpot的位置记录的是拖拽开始点在被拖拽widget中的相对位置 QList hotSpotPos = mime->data("application/x-hotspot").split(' '); //类型application/x-hotspot是在下面的mousePressEvent事件处理器中定义的。 if (hotSpotPos.size() == 2) { hotSpot.setX(hotSpotPos.first().toInt()); hotSpot.setY(hotSpotPos.last().toInt()); } foreach (QString piece, pieces) { //如上所述,有可能拖动了好多label进来,所以需要foreach循环 DragLabel *newLabel = new DragLabel(piece, this); newLabel->move(position - hotSpot); //放置新的label.为什么要减去hotSpot的坐标,参考上面对hotSpot的解释。 newLabel->show(); newLabel->setAttribute(Qt::WA_DeleteOnClose); position += QPoint(newLabel->width(), 0); } if (event->source() == this) { //如果拖动的源widget是本widget的时,那么此时的拖动操作被设为Move action. event->setDropAction(Qt::MoveAction); //设置为moveaction.我理解为设置返回值,其他不做什么具体的事情 event->accept(); } else { event->acceptProposedAction(); } } else { event->ignore(); } foreach (QObject *child, children()) { //此处有必要么? if (child->inherits("QWidget")) { QWidget *widget = static_cast(child); if (!widget->isVisible()) widget->deleteLater(); //此函数表示,当跳出此事件处理函数,进入事件循环的时候,就删除这些widget. } }}void DragWidget::mousePressEvent(QMouseEvent *event) //当按键被按下的时候,进入此event handler{ QLabel *child = static_cast(childAt(event->pos())); //返回在此widget中pos位置的widget if (!child) return; QPoint hotSpot = event->pos() - child->pos(); //相对于child的相对位置,从此处可见dropEvent中的hotSpot的适用,返回鼠标点击点在widget中的相对位置 QMimeData *mimeData = new QMimeData; //因为需要自定义此事件携带的数据,所以建立一个QMimeData对象 mimeData->setText(child->text()); //插入文字 mimeData->setData("application/x-hotspot", QByteArray::number(hotSpot.x()) + " " + QByteArray::number(hotSpot.y())); //注意,此处实际上定义了一个key类型为application/x-hotspot,此key的value为hotSpot的坐标,以空格分开 QPixmap pixmap(child->size()); child->render(&pixmap); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); drag->setPixmap(pixmap); drag->setHotSpot(hotSpot); Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction); //此函数启动拖拽的操作,直到操作结束,是一个阻塞型的操作,在windows上 if (dropAction == Qt::MoveAction) //我草,原来设为MoveAction只是置了一个flag啊 child->close(); //将widget设置为不显示}
- Qt实例学习--事件处理和简单拖拽实现原理
- Qt中事件处理的方法和实例
- Qt的事件处理和定时器解析(实例解析)
- Qt事件处理器和事件过滤器实例
- Qt事件处理器和事件过滤器实例
- Qt事件处理器和事件过滤器实例
- Qt事件处理器和事件过滤器实例
- Qml实现对鼠标和键盘事件的简单处理
- Android 事件分发 OnClickListener 和 OnTouchListener 的事件处理原理简单描述
- ABAP面向对象事件处理-简单实例
- Qt学习笔记(六) 事件处理
- Qt学习笔记(三)事件处理
- QT学习之事件处理(一)
- Qt学习笔记——事件处理
- Qt的事件处理和定时器解析
- Qt学习之路_10(Qt中statusBar,MessageBox和Timer的简单处理)
- Qt学习之路_10(Qt中statusBar,MessageBox和Timer的简单处理)
- qt学习:Qt中statusBar,MessageBox和Timer的简单处理
- 正则表达式
- 当前几个主要的Lucene中文分词器的比较
- Good develpmental prospect of rechargeable battery wholesale
- 用两个栈实现一个队列的功能...
- SQL Server2000安装错误解决方法
- Qt实例学习--事件处理和简单拖拽实现原理
- 我的小臭宝
- pragma预处理指令详解
- 排序算法 选择算法
- Lua+VC2008在win7下配置
- spring step 1 : 什么是spring
- C# 中的委托和事件
- The world is flat
- CDATA 节 [XML 标准]