现在的位置: 首页 > 综合 > 正文

Qt Drag与Drop 学习

2013年09月02日 ⁄ 综合 ⁄ 共 3438字 ⁄ 字号 评论关闭
Drag
要启动Drag操作,需要:

创建一个 QDrag 对象
调用该对象的 exec() 函数
启动 Drag 的时机

简单的情况,直接在 mousePressEvent 中启动drag操作
更常规的,在 mousePressEvent 中做个位置标志,在 mouseMoveEvent 中启动 drag 操作。
创建 QDrag 对象
Drag和Drop的过程,其实就是一个数据传递的过程。那么数据保存在哪儿呢?这便是 QMimeData

QDrag *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是什么呢?就是图片中的哪一个点对应光标位置。

QMimeData
QMimeData 内部其实是一个结构体的list

struct 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::IgnoreAction

Drop
要接受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.html

http://doc.qt.nokia.com/4.7/qdrag.html

为了您的安全,请只打开来源可靠的网址
打开网站 取消
来自: http://hi.baidu.com/cyclone/blog/item/081c9e2f248bf8281f308993.html

抱歉!评论已关闭.