Qt Drag与Drop 学习

来源:互联网 发布:域名强制回收 知乎 编辑:程序博客网 时间:2024/06/05 20:07
Drag要启动Drag操作,需要:创建一个 QDrag 对象 调用该对象的 exec() 函数 启动 Drag 的时机简单的情况,直接在 mousePressEvent 中启动drag操作 更常规的,在 mousePressEvent 中做个位置标志,在 mouseMoveEvent 中启动 drag 操作。 创建 QDrag 对象Drag和Drop的过程,其实就是一个数据传递的过程。那么数据保存在哪儿呢?这便是 QMimeDataQDrag *drag = new QDrag(this);QMimeData *mimeData = new QMimeData;mimeData->setData(mimeType, data);drag->setMimeData(mimeData);在拖拽过程中,我们可能希望看到一个被拖拽的对象跟随鼠标一块移动。其实,这是和鼠标一块动的是一个图片QPixmap pixmap(child->size());child->render(&pixmap);QDrag *drag = new QDrag(this);drag->setMimeData(mimeData);drag->setPixmap(pixmap);drag->setHotSpot(hotSpot);将要拖拽的对象(一个QWidget)直接render到一个图片中,然后将图片设置到 drag 对象。上面的hotSpot是什么呢?就是图片中的哪一个点对应光标位置。QMimeDataQMimeData 内部其实是一个结构体的liststruct QMimeDataStruct{ QString format; QVariant data;};操作这个list的是QMimeDataPrivate的成员函数void QMimeDataPrivate::setData(const QString &format, const QVariant &data)QVariant QMimeDataPrivate::getData(const QString &format) constQMimeData提供的 setData/setText/setHtml/setImageData 都是通过上面这个函数实现的。比如:void QMimeData::setText(const QString &text){ Q_D(QMimeData); d->setData(QLatin1String("text/plain"), text);}void QMimeData::setData(const QString &mimeType, const QByteArray &data){ Q_D(QMimeData); d->setData(mimeType, QVariant(data));}调用 exec 成员两个 exec 成员函数:Qt::DropAction QDrag::exec ( Qt::DropActions supportedActions = Qt::MoveAction )Qt::DropAction QDrag::exec ( Qt::DropActions supportedActions, Qt::DropAction defaultDropAction )前者是通过调用后者实现的:Qt::DropAction QDrag::exec(Qt::DropActions supportedActions){ return exec(supportedActions, Qt::IgnoreAction);}看一下代码:Qt::DropAction QDrag::exec(Qt::DropActions supportedActions, Qt::DropAction defaultDropAction){ Q_D(QDrag); if (!d->data) { qWarning("QDrag: No mimedata set before starting the drag"); return d->executed_action; } QDragManager *manager = QDragManager::self(); d->defaultDropAction = Qt::IgnoreAction; d->possible_actions = supportedActions; if (manager) { if (defaultDropAction == Qt::IgnoreAction) { if (supportedActions & Qt::MoveAction) { d->defaultDropAction = Qt::MoveAction; } else if (supportedActions & Qt::CopyAction) { d->defaultDropAction = Qt::CopyAction; } else if (supportedActions & Qt::LinkAction) { d->defaultDropAction = Qt::LinkAction; } } else { d->defaultDropAction = defaultDropAction; } d->executed_action = manager->drag(this); } return d->executed_action;}其中 d->executed_action 默认值是 Qt::IgnoreAction,基本可以看出:当我们的 defaultDropAction 为 Qt::IgnoreAction 时,首先会尝试转换成move、copy或link当不能正常执行时,返回值是 Qt::IgnoreActionDrop要接受Drop动作,首先Widget要设置setAcceptDrops(true);然后,需要override两个成员函数dragEnterEvent dropEvent dragEnterEvent必须处理该事件,不然 drop 不可用。void Window::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("text/plain")) event->acceptProposedAction(); }QDropEvent先看一下3个事件的继承关系:QDropEvent QDragMoveEvent QDragEnterEvent 看一个 QDropEvent 与 QEvent 的不同(对比一下二者的构造函数):QEvent::QEvent(Type type) : d(0), t(type), posted(false), spont(false), m_accept(true){}QDropEvent::QDropEvent(...){... ignore();}可知,一般的QEvent的 m_accept 默认为true,而QDropEvent默认为 false。这说明什么呢?处理一般的 QEvent 时,不需要调用 accept(),只需在必要时调用 ignore() 即可 处理 QDropEvnet 时,需要显式调用 accept() 来表示接受事件;不然等同于调用 ignore() acceptProposedAction()是什么东西?看下源码:inline void acceptProposedAction() { drop_action = default_action; accept(); }恩,比较清楚,等同于先设置默认的 drop_action,再对事件调用 accept()这样,就不难理解,为何有时用下面的写法了if (event->source() == this) { event->setDropAction(Qt::MoveAction); event->accept();} else { event->acceptProposedAction();}一个是默认动作,一个是move动作,对应的drag的启动命令drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);参考http://doc.qt.nokia.com/4.7/dnd.htmlhttp://doc.qt.nokia.com/4.7/qdrag.html为了您的安全,请只打开来源可靠的网址打开网站 取消来自: http://hi.baidu.com/cyclone/blog/item/081c9e2f248bf8281f308993.html
原创粉丝点击