前言
Qt 的拖放,在刚接触时,整个人感觉乱糟糟的。到现在,整理资料也是有点排斥的。但是没办法,为了使用方便,还是整理下吧。
Qt 的拖放,就是拖 Drag,和放 Drop。在做拖放时,要理好思路,哪个是移动方,哪个是接受方,当然,也可以既是移动方,也是接受方。下面,我将以这两个对象为方向,进行叙述。
移动方
拖放是通过鼠标实现的,所以这和鼠标事件QMouseEvent是分不开的。移动方实现的动作是,按下需要移动的对象,将其移动到目标地,简化就是:按下、移动,所以用到了 voidmousePressEvent(QMouseEvent*event);和
voidmouseMoveEvent(QMouseEven*event);
在这个的基础上,我又创建了方法performDrag() 用于保存需要传递的数据(我的这个例子是QListWidget)。说到数据,可以看到下面一个陌生的类QMimeData,官方上的解释说它是一个记录mime类型数据的容器,一般用在拖放,和剪贴板上。
用QMimeData保存数据,然后创建QDrag对象,我设置他的动作是复制Qt::CopyAction,当然,也可以是Qt::MoveAction 等。
void DragList::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) //按下左键
startPos = event->pos();
QListWidget::mousePressEvent(event); //确保QListWidget 可以像平常一样可以处理鼠标按下事件
}
void DragList::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
int distance = (event->pos() - startPos).manhattanLength(); //绝对值
if (distance >= QApplication::startDragDistance()) //要大于拖动其实距离 , 避免手抖而产生拖动
performDrag();
}
QListWidget::mouseMoveEvent(event);
}
void DragList::performDrag()
{
QList<QListWidgetItem*> list=selectedItems();
foreach (QListWidgetItem* item, list) {
if (item) {
QMimeData *mimeData = new QMimeData;
QString str=item->text();
mimeData->setText(str);
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(QPixmap(":/images/person.png"));
drag->start(Qt::CopyAction);
}
}
}
接受方
想象一下接受方的动作:拖动的对象进入,然后移动到目标位置,放下。也就是:拖动进入,拖动移动,放下,用代码来表示是:
void dragEnterEvent(QDragEnterEvent *);
void dragMoveEvent(QDragMoveEvent *);
void dropEvent(QDropEvent *);
在拖动进入和移动时,我设置了一个条件:如果属于本类的,就是children,将其动作改为移动,如果不是就接收目标的动作。也可以直接接收这个动作,但不能不写这两个事件,不然就不会有拖动。
void DragWidget::dragEnterEvent(QDragEnterEvent *e)
{
if (e->mimeData()->hasText())
{
if(children().contains(e->source()))
{
e->setDropAction(Qt::MoveAction);
e->accept();
}
else
e->acceptProposedAction();
}
}
void DragWidget::dragMoveEvent(QDragMoveEvent *e)
{
if (e->mimeData()->hasText())
{
if(children().contains(e->source()))
{
e->setDropAction(Qt::MoveAction);
e->accept();
}
else
e->acceptProposedAction();
}
}
void DragWidget::dropEvent(QDropEvent *e)
{
addItem(e->mimeData()->text());
e->setDropAction(Qt::CopyAction); //将事件作为“移动动作”来接受,从而告诉原窗口部件现在可以删除原来的移动项了
e->accept();
}
总结
这个是我对拖动的理解,也是根据网上例子的学习和自己的尝试。 其实,这么看来还是比较简单的。
本文详细介绍了Qt中拖放(Drag and Drop)功能的实现原理和步骤,包括移动方和接受方的处理方法,以及QMimeData和QDrag类的应用。


被折叠的 条评论
为什么被折叠?



