[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
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.