Qt:自定义拖放操作

功能:实现在一个窗口中任意拖动图片;

头文件:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtGui>
#include <QLabel>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

protected:
    void mousePressEvent(QMouseEvent *event);        //鼠标按下事件
    void dragEnterEvent(QDragEnterEvent *event);    //拖进事件
    void dragMoveEvent(QDragMoveEvent *event);     //拖动事件
    void dropEvent(QDropEvent *event);            //放下事件

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
源文件:

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setAcceptDrops(true);                           //接收拖放
    QLabel *label = new QLabel(this);
    QPixmap pixmap(":/new/prefix1/Image/m5.png");
    label->setPixmap(pixmap);
    label->resize(pixmap.size());
    label->move(100,100);
    label->setAttribute(Qt::WA_DeleteOnClose);     //关闭窗口时销毁图片
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::mousePressEvent(QMouseEvent *event)    //鼠标按下事件
{
    //将鼠标指向的部件强转为QLabel
    QLabel *child = static_cast<QLabel *>(childAt(event->pos()));
    if(!child->inherits("QLabel"))
    {
        return;
    }
    QPixmap pixmap = *child->pixmap();

    //创建数据流
    QByteArray itemData;
    QDataStream dataStream(&itemData,QIODevice::WriteOnly);
    dataStream << pixmap << QPoint(event->pos() - child->pos());
    //自定义MIME
    QMimeData *mimeData = new QMimeData;
    mimeData->setData("myimage/png",itemData);
    //创建拖动项
    QDrag *drag = new QDrag(this);
    drag->setMimeData(mimeData);
    drag->setPixmap(pixmap);
    drag->setHotSpot(event->pos() - child->pos());//设置热点保持鼠标点住图片时,位置不变
    //将原图片添加阴影
    QPixmap tempPixmap = pixmap;
    QPainter painter;
    painter.begin(&tempPixmap);
    painter.fillRect(pixmap.rect(),QColor(127,127,127,127));
    painter.end();
    child->setPixmap(tempPixmap);
    // 设置拖放可以是移动和复制操作,默认是复制操作
    if(drag->exec(Qt:: CopyAction | Qt::MoveAction,Qt::CopyAction)
            == Qt::MoveAction)
    {
        child->close(); // 如果是移动操作,那么拖放完成后关闭标签
    }
    else
    {
        child->show();
        child->setPixmap(pixmap);   //复制原图片
    }
}

void MainWindow::dragEnterEvent(QDragEnterEvent *event) //拖进事件
{
    //如果有自定义的MIME类型数据,则进行移动操作
    if(event->mimeData()->hasFormat("myimage/png"))
    {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
    else
    {
        event->ignore();
    }
}

void MainWindow::dragMoveEvent(QDragMoveEvent *event)   //拖动事件
{
    if(event->mimeData()->hasFormat("myimage/png"))
    {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
    else
    {
        event->ignore();
    }
}

void MainWindow::dropEvent(QDropEvent *event)   //放下事件
{
    if(event->mimeData()->hasFormat("myimage/png"))
    {
        QByteArray itemData = event->mimeData()->data("myimage/png");
        QDataStream dataStream(&itemData,QIODevice::ReadOnly);
        QPixmap pixmap;
        QPoint offset;
        //使用数据流将字节数组中的数据读入到QPixmap和QPoint变量中
        dataStream >> pixmap >> offset;

        QLabel *newLabel = new QLabel(this);
        newLabel->setPixmap(pixmap);
        newLabel->resize(pixmap.size());
        //让图片移动到放下的位置,否则,图片会默认显示在(0,0)点即窗口左上角
        newLabel->move(event->pos() - offset);
        newLabel->show();

        newLabel->setAttribute(Qt::WA_DeleteOnClose);
        event->setDropAction(Qt::MoveAction);
        event->accept();//完成事件,否则原图片不会消失
    }
    else
    {
        event->ignore();//驳回事件
    }
}
运行效果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值