c++qtqlabelqt6

Make Custom QLabel Dragable c++


I have created a custom QLabel class and am trying to make it dragable. I have tried my best but have failed in doing so. I saw many related questions, also tried chatgpt but could not get desired results. All events are called as expected except the DropEvent. The qlabeldragdrop.h has the custom class defined

#ifndef QLABELDRAGDROP_H
#define QLABELDRAGDROP_H

#include <QLabel>

class QLabelDragDrop : public QLabel
{
    Q_OBJECT
public:
    explicit QLabelDragDrop(QWidget *parent = nullptr);
protected:
    void mousePressEvent(QMouseEvent *event);
    void dragEnterEvent(QDragEnterEvent *event);
    void dragLeaveEvent(QDragLeaveEvent *event);
    void dragMoveEvent(QDragMoveEvent *event);
    void dropEvent(QDropEvent *event);
signals:

public slots:
};

#endif // QLABELDRAGDROP_H

The following is the declaration of the Custom QLabel class in qlabeldragdrop.cpp

#include "qlabeldragdrop.h"
#include <QDebug>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QMimeData>
#include <QDrag>

void QLabelDragDrop::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        QPixmap pixmap("C:\\Users\\Farhan Ahmed\\Documents\\untitled\\drag.png");
        QMimeData *mimeData = new QMimeData;
        mimeData->setImageData(pixmap); // set the image data
        QDrag *drag = new QDrag(this);
        drag->setMimeData(mimeData); // set the mime data
        drag->setPixmap(pixmap); // set the pixmap
        drag->setHotSpot(event->pos());
        drag->exec(Qt::MoveAction | Qt::CopyAction);
    }
}


QLabelDragDrop::QLabelDragDrop(QWidget *parent) : QLabel(parent)
{
    setAcceptDrops(true);
    setMouseTracking(true);
}

void QLabelDragDrop::dragEnterEvent(QDragEnterEvent *event)
{
    qDebug() << "dragEnterEvent";
    event->acceptProposedAction();
}

void QLabelDragDrop::dragLeaveEvent(QDragLeaveEvent *event)
{
    qDebug() << "dragLeaveEvent";
    releaseMouse();
}

void QLabelDragDrop::dragMoveEvent(QDragMoveEvent *event)
{
    event->acceptProposedAction(); // accept the proposed action
    qDebug() << "dragMoveEvent";
}

void QLabelDragDrop::dropEvent(QDropEvent *event)
{
    event->acceptProposedAction();
    qDebug() << "dropEvent";
}


The mainwindow.h has the following code


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QLabel>
#include <QPainter>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow

{
    Q_OBJECT
    int label_count = 0;
    QLabel *my_label = nullptr;
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void myAwesomeFunc();
    void drawLineBetweenLabelAndGroupBox(QLabel *label);

protected:
    void paintEvent(QPaintEvent* event) override;

private:
    Ui::MainWindow *ui;

};

#endif // MAINWINDOW_H

In the mainwindow.cpp file the Custom QLabel is being created.


#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "qlabeldragdrop.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QObject::connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::myAwesomeFunc);
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::paintEvent(QPaintEvent* event) {
    QMainWindow::paintEvent(event);
    char c[] = "label_";
    //QString num = QString::number(label_count);
    //QString name = QString::fromUtf8(c, 6);
    //QLabel* my_label = ui->centralwidget->findChild<QLabel*>(name + num);

    if (my_label != nullptr){
        QPainter painter(this);
        painter.setPen(QPen(Qt::black, 2));
        QPoint start = my_label->frameGeometry().center();
        QPoint end = ui->groupBox->frameGeometry().center();
        painter.drawLine(start, end);
        label_count++;
    }
}

void MainWindow::myAwesomeFunc(){
    QLabelDragDrop *label = new QLabelDragDrop(ui->centralwidget);
    label->setGeometry(QRect(20,20,80,40));
    char c[] = "label_";
    QString num = QString::number(label_count);
    QString name = QString::fromUtf8(c, 6);
    label->setObjectName(name + num);
    label->setText("New Label");
    //label->setParent(ui->centralwidget);
    label->show();
    my_label = label;
    update();
}

The main.cpp file is


#include "mainwindow.h"

#include <QApplication>


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

I am complete newbie to Qt and also do not have much experience in cpp. I have tried my best spending 3 days and failed to do so. Thanks in advance for any help.


Solution

  • The thing that I've noticed at the first glance, the QLabel derived class has its own mouse event methods, it shouldn't. These mouse events needs to be overridden in the widget which you want to make the operations on it(e.g. mainwindow).

    have some inspiration from this example, it is exactly the same implementation you want.