[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(). -
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_OBJECTpublic:
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".