Qt Drag&Drop拖动与放置

本文章从属于  Qt实验室-CSDN博客系列

拖放操作包括两个动作:拖动(drag)和放下(drop或称为放置)。

拖动允许

对于要拖出的窗口或控件,要setDragEnabled(true)

对于要拖入的窗口或控件,要setAcceptDrops(true)

下面以一个具体的用例进行说明

拖动列表控件中的项目

该用例实现从左边的列表窗口拖出,到右边的Widget窗口拖入

主界面设置

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    this->resize(1200,800);
    //从ProjectListWidget拖动到MyWidget上
    QSplitter* center=new QSplitter;
    center->addWidget(new ProjectListWidget);
    center->addWidget(new MyWidget);

    center->setOrientation(Qt::Horizontal);
    this->setCentralWidget(center);
}

 左侧列表窗口设置

class ProjectListWidget : public QListWidget
{
    Q_OBJECT
public:
    ProjectListWidget();

    // QAbstractItemView interface
protected:
    void startDrag(Qt::DropActions supportedActions);
};

 左侧窗口允许拖动其item,并且将item中的文字存入QMimeData,用以传输到右侧窗体中


ProjectListWidget::ProjectListWidget()
{
    this->addItem("item1");
    this->addItem("item2");
    //(1)开启允许拖动,如果不开启是不会有拖动item移动的效果的
    this->setDragEnabled(true);
}

//(2)开始拖动,设置了一种标记为x1的拖动数据
void ProjectListWidget::startDrag(Qt::DropActions supportedActions)
{
    QString text=this->currentItem()->text();
    QMimeData* mimeData=new QMimeData;
    mimeData->setData("x1",text.toLocal8Bit());
    QDrag* drag=new QDrag(this);
    drag->setMimeData(mimeData);
    drag->exec();
}

 右侧窗体的实现会多些,首先必须允许拖拽进入事件dragEnterEvent,然后必须允许拖拽移动事件dragMoveEvent。最后实现dropEvent来接收数据。


MyWidget::MyWidget(QWidget *parent)
    : QWidget{parent}
{
    //(1)开启允许放置,如果不开启,拖动进入界面时将显示禁止符号
    this->setAcceptDrops(true);
}

//(2)实现了以下两个方法后,该界面就能允许拖拽进入了
//对一种被标记为x1的拖动数据允许拖拽进入
void MyWidget::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat("x1"))
        event->accept();
    else
        event->ignore();
}

void MyWidget::dragMoveEvent(QDragMoveEvent *event)
{
    if (event->mimeData()->hasFormat("x1"))
        event->accept();
    else
        event->ignore();
}

//(3)实现dropEvent来接收拖动携带的数据
void MyWidget::dropEvent(QDropEvent *event)
{
    if (event->mimeData()->hasFormat("x1"))
    {
        QString text(event->mimeData()->data("x1"));
        QPoint pos=event->pos();
        //在这里将拖动过来的数据放入list,然后通过paintEvent()进行绘制
        m_textList.append({text,pos});
        event->accept();
        this->update();
    }
    else
        event->ignore();
}

void MyWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    for(int i=0;i

最终的效果如下

Qt Drag&Drop拖动与放置_第1张图片

  事件发出顺序和传递规则

Qt Drag&Drop拖动与放置_第2张图片

上图参考自 Qt拖放(1):拖放基本原理(QDrag类)-CSDN博客

关于 QDrag.exec()

void ProjectListWidget::startDrag(Qt::DropActions supportedActions)
{
    //调用该方法的时机,点击item并移动鼠标,即进入该方法
    //然后执行到drag->exec()阻塞
    //exec()函数是一个阻塞函数(但不会阻塞主事件循环)
    //也就是说,在松开鼠标之前,不会打印"after drag"
    //但是窗口依然可以得到其他的事件响应,例如mainwindow依然可以响应QTimer触发的update()
    QString text=this->currentItem()->text();
    QMimeData* mimeData=new QMimeData;
    mimeData->setData("x1",text.toLocal8Bit());
    QDrag* drag=new QDrag(this);
    drag->setMimeData(mimeData);
    qDebug()<<"before drag";
    drag->exec();
    qDebug()<<"after drag";
}

MainWindow中构造时添加如下代码, 

    QTimer* timer=new QTimer(this);
    timer->setInterval(1000);
    connect(timer,&QTimer::timeout,[=]{
        qDebug()<<"update...";
        this->update();
    });
    timer->start();

 测试在拖拽中不释放鼠标时,主窗口能否响应其他的事件(是可以的)

bool MainWindow::event(QEvent *event)
{
    qDebug()<<"event::"<

拖动Widget中的内容到另外一个窗口或控件

以上示例开启拖动的时机在startDrag()方法内,QListWidget::startDrag()可以供重写使用,但是对于普通的QWidget来说,并没有该方法可用

 本示例以一个继承自QWidget的LeftWidget为例说明,通常在mousePressEvent()中去开启拖动

void LeftWidget::mousePressEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton)
    {
        QString text="xxxxxxx";
        QMimeData* mimeData=new QMimeData;
        mimeData->setData("x1",text.toLocal8Bit());
        QDrag* drag=new QDrag(this);
        drag->setMimeData(mimeData);
        qDebug()<<"before drag";
        drag->exec();
        qDebug()<<"after drag";
    }
}

继续使用上一个示例的MainWindow和MyWidget,实现从LeftWidget拖动到MyWidget的效果

Qt Drag&Drop拖动与放置_第3张图片

如果要实现从拖动按钮到另外一个界面上,使其文字到另外一个窗口

可以通过继承QPushButton然后重写其mousePressEvent,几乎与重写LeftWidget::mousePressEvent一样。

void MyButton::mousePressEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton)
    {
        QString text=this->text();
        QMimeData* mimeData=new QMimeData;
        mimeData->setData("x1",text.toLocal8Bit());
        QDrag* drag=new QDrag(this);
        drag->setMimeData(mimeData);
        qDebug()<<"before drag";
        drag->exec();
        qDebug()<<"after drag";
    }
    return QPushButton::mousePressEvent(event);
}

Qt Drag&Drop拖动与放置_第4张图片 

你可能感兴趣的:(qt,数据库,开发语言)