拖放 Drag 、Drop--Qt

本文详细介绍了Qt中拖放(Drag and Drop)功能的实现原理和步骤,包括移动方和接受方的处理方法,以及QMimeData和QDrag类的应用。

前言   

 

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();
}

 

总结

 

这个是我对拖动的理解,也是根据网上例子的学习和自己的尝试。 其实,这么看来还是比较简单的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十年之少

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值