首页 > 解决方案 > 如何在 Qt 中将 QLabel 从一个窗口拖到另一个窗口?

问题描述

我学习 Qt 是为了好玩。我有一个问题:

我如何在两个不同的窗口之间拖放 Qt 中的 QLabel?

这是我到目前为止所拥有的:

在此处输入图像描述

正如您从上面提供的.gif(由于某些原因不想被下载并在此处显示,但如果您单击它的链接,您可以清楚地看到它)可以看出,现在有两个主要问题:

  1. 我无法移动QLabel窗口的外部(因此无法注册拖放事件)。

  2. 当我移动它时,标签由于某些原因闪烁。

以下是实现的相关部分.gif

#ifndef DRAGGERP_H
#define DRAGGERP_H

#include <QLabel>
#include <QApplication>
#include <QMouseEvent>
#include <QPoint>

class DraggerP : public QLabel
{
    QPoint offset;
    QPoint startingPosition;


public:
    DraggerP(QWidget* parent = nullptr) : QLabel(parent){ }

protected:
    void enterEvent(QEvent* event) override
    {
        QApplication::setOverrideCursor(Qt::PointingHandCursor);
    }

    void leaveEvent(QEvent* event) override
    {
        QApplication::restoreOverrideCursor();
    }

    void mousePressEvent(QMouseEvent* event) override
    {
        startingPosition = pos();
        offset = QPoint(
            event->pos().x() - pos().x() + 0.5*width(),
            event->pos().y() - pos().y() + 0.5*height()
        );
    }

    void mouseMoveEvent(QMouseEvent* event) override
    {
        move(event->pos() + offset);
    }

    void mouseReleaseEvent(QMouseEvent* event) override
    {
        move(startingPosition);
    }
};

#endif // DRAGGERP_H

这是QLabel我用来创建拖放效果的扩展。

我不需要整个解决方案,至少需要知道如何完成此任务以及我在这里做错了什么。

是一个很好的例子,我用它作为起点。

标签: c++qtdrag-and-dropqt5qlabel

解决方案


遭受这种奇怪的运动QLabel是因为QLabel现在的位置取决于布局,布局的工作是根据您建立的策略确定小部件的位置。

解决方案不是在 MainWindow 中QLabel而是在 MainWindow 中实现这些操作,如下所示:

#include <QApplication>
#include <QLabel>
#include <QMainWindow>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QTime>
#include <QDrag>
#include <QMimeData>
#include <QMouseEvent>

class MainWindow: public QMainWindow {
    QScrollArea scrollArea;
    QWidget contentWidget;
    QVBoxLayout lay;
public:
    MainWindow(QWidget* parent=nullptr): QMainWindow(parent){
        qsrand((uint) QTime::currentTime().msec());
        setCentralWidget(&scrollArea);
        scrollArea.setWidget(&contentWidget);
        contentWidget.setLayout(&lay);
        scrollArea.setWidgetResizable(true);
        for(int i=0; i< 20; i++){
            QLabel *label = new QLabel(QString("label %1").arg(i));
            QPalette pal = label->palette();
            pal.setColor(QPalette::Background, QColor(10 +qrand() % 240, 10 +qrand() % 240, 10 +qrand() % 240));
            label->setAutoFillBackground(true);
            label->setPalette(pal);
            lay.addWidget(label);
        }
        setAcceptDrops(true);
    }
protected:
    void mousePressEvent(QMouseEvent *event){
        QMainWindow::mousePressEvent(event);
        QWidget *child = childAt(event->pos());
        if(qobject_cast<QLabel *>(child))
            createDrag(event->pos(), child);
    }

    void dropEvent(QDropEvent *event){
        QByteArray byteArray = event->mimeData()->data("Label");
        QWidget * widget = *reinterpret_cast<QWidget**>(byteArray.data());
        QLabel * new_label =  qobject_cast<QLabel *>(widget);

        QWidget *current_children = childAt(event->pos());
        QLabel * current_label = qobject_cast<QLabel*>(current_children);
        int index = 0;
        if(new_label){
            if(current_label)
                index = lay.indexOf(current_label);
            else{
                index = 0;
                QLayoutItem *item = lay.itemAt(index);
                while(item->widget()->pos().y() < event->pos().y() && item) 
                    item = lay.itemAt(index++);
            }
            lay.insertWidget(index, new_label);
        }
    }

private:
    void createDrag(const QPoint &pos, QWidget *widget){
        if(widget == Q_NULLPTR)
            return;
        QByteArray byteArray(reinterpret_cast<char*>(&widget),sizeof(QWidget*));
        QDrag *drag = new QDrag(this);
        QMimeData * mimeData = new QMimeData;
        mimeData->setData("Label",byteArray);
        drag->setMimeData(mimeData);
        QPoint globalPos = mapToGlobal(pos);
        QPoint p = widget->mapFromGlobal(globalPos);
        drag->setHotSpot(p);
        drag->setPixmap(widget->grab());
        drag->exec(Qt::CopyAction | Qt::MoveAction);
    }
protected:
    void dragEnterEvent(QDragEnterEvent *event){
       if(event->mimeData()->hasFormat("Label"))
        event->acceptProposedAction();
    }
};

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

推荐阅读