Qt中自定义控件拖拽,QT实现拖拽功能--小白友好版

目录

创作背景

开发环境

 运行效果

实现原理

        1.参考文档       

       2.主要原理 

实现过程

        1.首先是重写QLabel

        2.第二步是使用自己写的Label类

总结


创作背景

        写这篇文章主要有一下几点原因。第一个呢就是小白学习qt,准备实现拖拽效果但是不会写。再一个就是在网上找到的教程都是参差不齐,没找到特别详细的,对小白友好的教程。所以在研究透彻之后供大家参考。有不正确的地方还请大家指正。

开发环境

        QT5.12.2 + win11 +minggw73

 运行效果

实现原理

        1.参考文档       

Qt拖拽,官方文档http://xn--gqq717c/

      MimaData文档https://doc.qt.io/archives/qt-5.5/qmimedata.html#setImageData

       2.主要原理 

        以QLabel为例,当鼠标按住QLabel会触发mousePressEvent(QMouseEvent *a_event)事件

,当你按住这个QLabel拖动一段距离时,会触发mouseMoveEvent(QMouseEvent *a_event)

事件。当鼠标拖动一个QLabel进入另外一个QLabel【也可以是它自己】时,会触发dragEnterEvent(QDragEnterEvent *a_event)事件,当鼠标拖动一个QLabel进入另外一个QLabel【也可以是它自己】并且松开鼠标时会触发dropEvent(QDropEvent *a_event)。

        但是,QLabel封装的时候并没有在这几个事件触发时添加处理逻辑。所以需要创建一个QLabel的子类,来重写这些事件函数,并且添加处理逻辑。

        好了,到此为止。需要用到的主要事件和在哪里触发就说完了。

实现过程

        1.首先是重写QLabel

                .h头文件

                

#ifndef DROPQLABEL_H
#define DROPQLABEL_H
#include<QLabel>
#include<QDragEnterEvent>
#include<QMimeData>
#include<QDrag>
#include<QDebug>
#include<QApplication>

class DropQLabel : public QLabel//公开继承QLabel
{
    Q_OBJECT
public:
    
    DropQLabel(QWidget *parent = nullptr);
    ~DropQLabel();
    //重写鼠标放下时事件处理函数
    void dropEvent(QDropEvent* a_event);
    //重写鼠标拖入时事件处理函数
    void dragEnterEvent(QDragEnterEvent* a_event);
    //重写鼠标按住时事件处理函数
    void mousePressEvent(QMouseEvent *a_event);
    //重写鼠标移动时事件处理函数
    void mouseMoveEvent(QMouseEvent *a_event);

};

#endif // DROPQLABEL_H

        .cpp文件

#include "dropqlabel.h"


DropQLabel::DropQLabel(QWidget *parent):QLabel(parent)//调用父类的构造函数
{
    //构造函数中可以没有内容,但是必须实现
}

DropQLabel::~DropQLabel()
{
    //析构函数也是,可以没有内容但是必须实现
}
//鼠标放下的事件
void DropQLabel::dropEvent(QDropEvent *a_event)
{
    QString a="我接受到拖拽内容了,内容是:"+a_event->mimeData()->text();//解析mamiData中携带的信息
    qDebug()<<a;
}
//鼠标拖入的事件
void DropQLabel::dragEnterEvent(QDragEnterEvent *a_event)
{
        // 如果拖动的事件中有Text,则允许drop。如果没有Text则不允许放下
       if (a_event->mimeData()->hasText())
       {
           // 如果未调用,则无法drop
           a_event->acceptProposedAction();
       }
}

void DropQLabel::mousePressEvent(QMouseEvent *a_event)
{
    
}

void DropQLabel::mouseMoveEvent(QMouseEvent *a_event)
{
    if (a_event->buttons() & Qt::LeftButton)//判断是否时鼠标的事件,且为左键则执行
        {
            QApplication::startDragDistance())
            //Qt中拖拽时需要生成一个Drag对象,才能实现拖拽
            这些事件声明也可以放在mousePressEvent(QMouseEvent *a_event)函数中
            QDrag *drag = new QDrag(this);
            //拖拽时也必须声明一个MimeData可以用来传递信息,如果不需要传递信息也要声明并且调用drag的setMimeData()函数,否则会报错。
            QMimeData *mimeData = new QMimeData;
            QString labelText=this->text();
            QString a="我开始被拖拽了,发送的拖拽内容是:"+this->text();
            this->setText(a);
            //可以调用mimeData的各种方法设置想要mimeData传递的信息
            mimeData->setText(labelText);
            drag->setMimeData(mimeData);
            drag->exec();//最后调用exec()即可
        }

}

QLabel的重写工作完成之后,也就完成了大半。

        2.第二步是使用自己写的Label类

                在QtCreator的ui编辑器中拖入一个QLabel右键单击,在快捷菜单中选择“提升为”选项。

在弹出的对话框中输入类名,点击添加

添加成功后选中类,点击对话框底部的提升按钮。

 看到下图处,类名改变则表示提升成功。

 最后在mainWindow的cpp代码构造函数中允许放下的动作setAcceptDrops(true);

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    DropQLabel* aa=this->findChild<DropQLabel *>("bbb");
    DropQLabel* bb=this->findChild<DropQLabel *>("aaa");
    //设置允许放下动作
    bb->setAcceptDrops(true);
    //再设置父UI框架为允许放下,否则会失败。
    this->setAcceptDrops(true);

}


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

 至此,所有工作已经完成。

总结

        大致步骤就是:重写QLabel=>使用自己写的控件=>在主窗口中设置允许鼠标放下动作。

        然后就是:

        Qt开发任重道远,加油吧!!

  • 11
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 在Qt实现控件拖拽功能有多种方法。以下是其一种常见的实现方式: 1. 首先,在Qt的窗口类重写mousePressEvent、mouseMoveEvent和mouseReleaseEvent三个鼠标事件函数。 2. 在mousePressEvent函数,判断是否按下了鼠标左键,若是,则记录下鼠标的当前位置,同时将需要进行拖拽的控件设置为鼠标捕获状态。例如: ```cpp void MyWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_dragStartPosition = event->pos(); m_isDragging = true; setMouseTracking(true); grabMouse(); event->accept(); } } ``` 3. 在mouseMoveEvent函数,判断是否处于拖拽状态,若是,则计算鼠标的位移距离,并更新需要拖拽的控件的位置。例如: ```cpp void MyWidget::mouseMoveEvent(QMouseEvent *event) { if (m_isDragging) { QPoint delta = event->globalPos() - m_dragStartPosition; move(m_dragStartPosition + delta); event->accept(); } } ``` 4. 在mouseReleaseEvent函数,判断是否松开了鼠标左键,若是,则将拖拽状态设置为false,并释放鼠标捕获状态。例如: ```cpp void MyWidget::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_isDragging = false; setMouseTracking(false); releaseMouse(); event->accept(); } } ``` 通过以上步骤,就可以实现Qt的控件拖拽功能。当鼠标按下左键并拖动控件时,控件会跟随鼠标的移动而移动。 ### 回答2: 在Qt实现控件拖拽功能通常可以通过以下步骤进行: 1. 首先,需要为控件设置属性 `setDragEnabled(true)`,以使其具有可拖拽的能力。 2. 在鼠标按下事件 `mousePressEvent` ,通过调用 `QDrag` 类的静态成员函数 `setMimeData` 来设置所需的拖拽数据。 3. 接下来,需要在 `mouseMoveEvent` 进行一些处理,使得控件能够跟随鼠标的移动进行拖拽。可以使用 `QDrag` 类的静态成员函数 `exec` 来启动拖拽操作。 4. 在目标控件的事件处理函数 `dragEnterEvent` ,需要通过 `event->mimeData()->hasFormat` 来判断拖拽数据是否符合预期,并将事件接受标志设置为 `true`。 5. 在目标控件的 `dropEvent` ,可以使用 `event->mimeData()` 获取拖拽数据,并进行相应的处理。 综上所述,通过设置控件的可拖拽属性,并在事件处理函数进行拖拽数据的设置和拖拽行为的处理,可以在Qt实现控件拖拽功能。 ### 回答3: 在Qt,可以通过以下步骤实现控件拖拽功能: 1. 创建一个自定义的控件类,并继承QWidget或QGraphicsItem类,这个类将成为可以拖拽的控件。 2. 在控件类的构造函数,使用setMouseTracking(true)启用鼠标追踪,以便在鼠标拖拽时能够实时检测鼠标位置。 3. 重写控件类的mousePressEvent、mouseMoveEvent和mouseReleaseEvent等事件处理函数,以实现拖拽效果。 4. 在mousePressEvent函数,检测鼠标按下事件,并记录鼠标按下时的位置。 5. 在mouseMoveEvent函数,检测鼠标移动事件,并计算鼠标的偏移量,然后使用move函数将控件按照偏移量进行移动。 6. 在mouseReleaseEvent函数,检测鼠标释放事件,并完成相应的拖拽操作,例如保存控件的新位置等。 7. 在主窗口或场景,将自定义的控件添加到需要拖拽的位置,并通过布局或手动设置位置进行定位。 通过以上步骤,就可以实现Qt的控件拖拽功能。在实际使用时,可以根据需要对拖拽过程进行优化,例如在拖拽过程显示边框或阴影效果,限制拖拽的范围等。同时,还可以通过重写eventFilter函数实现对其他控件的拖拽支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值