代码之家  ›  专栏  ›  技术社区  ›  manymanymore

如何在Qt中将QLabel从一个窗口拖动到另一个窗口?

  •  0
  • manymanymore  · 技术社区  · 6 年前

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

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

    以下是我目前掌握的情况:

    enter image description here

    正如你从照片上看到的 .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 我正在使用创建拖放效果。

    我不需要完整的解决方案,至少需要一个如何实现这一点以及我在这里做错了什么的想法。

    Here 这是一个很好的例子,我以此为出发点。

    1 回复  |  直到 6 年前
        1
  •  1
  •   eyllanesc    6 年前

    那个奇怪的动作 QLabel 痛苦是因为 QLabel 现在取决于布局,布局的工作是根据您建立的策略确定小部件的位置。

    解决办法是不在未来实施这些行动 QLabel 但在主窗口中,如我所示:

    #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();
    }