Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[SOLVED] How to set drop area on frame without using a SubClass



  • I'm using Qt 5.3.2 (QtCreator 3.2.1). I have a working drag/drop example that has two forms. I can drag from one form and drop onto the other form. I'm trying to limit the drop area on the drop form to a QLabel on the drop form.
    What do I need to do, in order to accomplish that?

    I have code in a DropOnlyFrame.ui GUI form and corresponding cpp/h files.

    @
    DropOnlyFrame::DropOnlyFrame() { ... calls setAcceptDrops(true) }
    DropOnlyFrame::dragEnterEvent() { ... calls event->acceptProposedAction(); }
    DropOnlyFrame::dropEvent() { ... copies pixmap to a new label }
    @

    I've created a QLabel, QFrame and QPushButton and enabled drops on each of them as shown:
    @
    ui->lblDropOnMe->setAcceptDrops( true );
    ui->btnDropOnMe->setAcceptDrops( true );
    ui->frameDropOnMe->setAcceptDrops( true );
    @

    but for some reason the

    @DropOnlyFrame::dragEnterEvent()@

    is not called (a debug statement is printed if it were called).

    Does the dragEnterEvent() need to be "connected" to the lblDropOnMe? Do I need to use a subclass (as is done in the dropsite example)?



  • I found if I call setAcceptDrops() on the GUI form (QFrame) as well as the other widgets as described in the original question, then DropOnlyFrame::dragEnterEvent() is called.

    So is there a way to know which widget I just entered?
    I see a QDragEnterEvent::source() but not a QDragEnterEvent::dest().


  • Lifetime Qt Champion

    Hi,

    You could try to setup an event filter and handle the QEvent::Drag(Enter/Leave/Move) and Drop events yourself.

    Hope it helps



  • Thanks for the suggestion. I'll look at QObject::installEventFilter() to see if the QDragEnterEvent can be observed. If so that should work.



  • It worked! Thanks for the suggestion. For others who might want to do this I added an eventFilter on the frame that held the widgets I wanted to drop on.

    When the Drag/Drop events happened I looked to see if the event was destined to one of my drop targets and if it was I called an appropriate handle drop method.

    Below is a snippet of what I did in a sample program. The code could be cleaned up a bit but it should be good enough for someone else who wants to try to do this.

    @
    // Header file DropOnlyFrame.h
    class DropOnlyFrame : public QFrame
    {
    Q_OBJECT

    public:
    explicit DropOnlyFrame( QWidget *parent = 0 );
    ~DropOnlyFrame();

    protected:
    bool eventFilter( QObject *obj, QEvent *event );

    private:
    void handleLabelDropEvent( QLabel* destLabel, QDropEvent *event );

    private:
    Ui::DropOnlyFrame *ui;
    };
    @

    Source file (snippet)
    @
    // Un-necessary code removed from example
    DropOnlyFrame::DropOnlyFrame(QWidget *parent)
    {
    ui->lblDropOnMe->setAcceptDrops( true );
    // Set an event filer so that I'll know if the
    ui->lblDropOnMe->installEventFilter( this );
    }

    bool DropOnlyFrame::eventFilter(QObject obj, QEvent event)
    {
    if ( obj == ui->lblDropOnMe)
    {
    if ( event->type() == QEvent::DragEnter )
    {
    qDebug() << "Looks like we got a DragEnter event for the label, whew hew!";
    QDragEnterEvent
    pDragEnterEvent = static_cast<QDragEnterEvent
    > (event);
    if (pDragEnterEvent->mimeData()->hasFormat("application/x-dnditemdata"))
    {
    pDragEnterEvent->acceptProposedAction();
    }
    return true;
    }
    else if ( event->type() == QEvent::Drop )
    {
    QDropEvent* pDragEnterEvent = static_cast<QDropEvent*> (event);
    QLabel* pDestLabel= static_cast<QLabel*> (obj);
    handleLabelDropEvent( pDestLabel, pDragEnterEvent );
    return true;
    }
    else
    {
    return ui->lblDropOnMe->eventFilter( obj, event );
    }
    }

    return obj->eventFilter( obj, event );
    

    }

    void DropOnlyFrame::handleLabelDropEvent(QLabel* destLabel, QDropEvent *event)
    {
    qDebug() << "DropOnlyFrame::handleLabelDropEvent";
    if (event->mimeData()->hasFormat("application/x-dnditemdata")) {
    QByteArray itemData = event->mimeData()->data("application/x-dnditemdata");
    QDataStream dataStream(&itemData, QIODevice::ReadOnly);

        QPixmap pixmap;
        QPoint offset;
        dataStream >> pixmap >> offset;
    
        destLabel->setPixmap(pixmap);
    
        event->acceptProposedAction();
    } else {
        event->ignore();
    }
    

    }

    @

    NOTE: Some of this code started from the Qt sample program named "draggableicons".


Log in to reply