QT Drag and Drop a QLabel into a QGraphicsView, how to?
-
Hi, all:
Sorry to bug you once again.
I'm trying to drag and drop a QLabel into a QGraphicsView.
My inherited label class looks like:
@class CQtShapesLabel : public QLabel
{
Q_OBJECTpublic:
explicit CQtShapesLabel(QWidget *parent = 0, int type = 0) : QLabel(parent), m_iType(type) {
// this->m_qMimeData = NULL;
// this->m_qDrag = NULL;
}virtual ~CQtShapesLabel() {}
protected:
// void dragEnterEvent(QDragEnterEvent *event);
// void dragMoveEvent(QDragMoveEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);private:
// QMimeData* m_qMimeData;
// QDrag * m_qDrag;
int m_iType;
};@and mousePressEvent() function is defined as:
@
void CQtShapesLabel::mousePressEvent(QMouseEvent *event)
{
QPixmap pixmap = *this->pixmap();QByteArray itemData; QDataStream dataStream(&itemData, QIODevice::WriteOnly); dataStream << pixmap << QPoint(event->pos()); QMimeData* m_qMimeData = new QMimeData; m_qMimeData->setData("application/x-dnditemdata", itemData); QDrag* m_qDrag = new QDrag(this); m_qDrag->setMimeData(m_qMimeData); m_qDrag->setPixmap(pixmap); m_qDrag->setHotSpot(event->pos()); QPixmap tempPixmap = pixmap; QPainter painter; painter.begin(&tempPixmap); painter.fillRect(pixmap.rect(), QColor(127, 127, 127, 127)); painter.end(); this->setPixmap(tempPixmap); if (m_qDrag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) == Qt::MoveAction) this->close(); else { this->show(); this->setPixmap(pixmap); }
}@
My inherited QGraphicsView class looks like:
@class QTVIEWS_EXPORT CImageView : public QGraphicsView
{
Q_OBJECTprotected:
//void paintEvent(QPaintEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dragLeaveEvent(QDragLeaveEvent *event);
void dropEvent(QDropEvent *event);
// void mousePressEvent(QMouseEvent *event);public:
CImageView( QWidget *parent = 0, unsigned int idx = 0 ); virtual ~CImageView( );
};@
When testing, I tried to print out something in all functions, but no matter how I tried, I found
bq. CQtShapesLabel::mouseReleaseEvent(QMouseEvent *event); // understandable
CImageView::dragLeaveEvent(QDragLeaveEvent *event); // should be able to response when the drag leaves this view
CImageView::dropEvent(QDropEvent *event); // should be able to response when the drag tries to drop something
CImageView::dragMoveEvent(QDragMoveEvent *event) // should be able to response when the drag keeps moving inside the viewnever responses. Why is it so? Can anybody help to explain please....
Best Regards
Pei -
Hi,
Did you "setAcceptDrops(true)" in your CImageView ?
-
Sorry but it is not really clear how you implemented receiving the "drops" - you only show what was in the header file of your subclassed QGraphicsView.
Anyways, if you actually want to drag and drop a QWidget (QLabel, etc) into a QGraphicsView/Scene, you need to use "QGraphicsProxyWidget":http://qt-project.org/doc/qt-4.8/qgraphicsproxywidget.html
Also, some devs, most of the time, forgets to enable "setAcceptDrops":http://doc-snapshot.qt-project.org/4.8/qwidget.html#acceptDrops-prop
-
Yes, I do have setAcceptDrops(true); in my code, which is the first line of CImageView constructor, before
@ ......
this->setScene( this->m_QTGraphicsScene );
this->show();@[quote author="SGaist" date="1362479189"]Hi,
Did you "setAcceptDrops(true)" in your CImageView ?[/quote]
-
Hi,
I hope that you are checking the mimeData format in each of the drag funcions like
@void CImageView::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("application/x-dnditemdata"))
{
event->accept();
} else
{
event->ignore();
}
}@Can you share the code of CImageView class , that will give the exact picture of your implementation.
-
Some more code is provided now:
VO_ImageView.h
@
#ifndef VO_IMAGEVIEW_H
#define VO_IMAGEVIEW_H#include "qtviews_global.h"
#include <QGraphicsView>
#include <QGraphicsPixmapItem>
#include <QGraphicsItem>
#include <QGraphicsLineItem>
#include <QGraphicsItemGroup>
#include <QLabel>
#include <QBoxLayout>
#include <QMouseEvent>using namespace std;
/**
show an image in the corresponding QGraphicsView
*/
class QTVIEWS_EXPORT CImageView : public QGraphicsView
{
Q_OBJECTprivate:
int m_iIdx;
QGraphicsScene* m_QTGraphicsScene;
QPixmap* m_QTBackGroundPixmap;
QGraphicsPixmapItem* m_QTBackGroundItem;void init()
{
this->m_QTGraphicsScene = NULL;
this->m_QTBackGroundPixmap = NULL;
this->m_QTBackGroundItem = NULL;
setAcceptDrops(true);
}protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);public:
CImageView( QWidget *parent = 0, unsigned int idx = 0 );
virtual ~CImageView( );
};#endif
@VO_ImageView.cpp
@
#include <QBuffer>// main header
#include "VO_ImageView.h"
#include "LV_QtShapesLabel.h"CImageView::CImageView(QWidget *parent, unsigned int idx): QGraphicsView(parent), m_iIdx(idx)
{
this->init();
this->m_QTGraphicsScene = new QGraphicsScene;
this->m_QTBackGroundItem = new QGraphicsPixmapItem;
this->setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff );
this->setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOff );
this->setScene( this->m_QTGraphicsScene );
this->show();
this->m_QTBackGroundPixmap = new QPixmap( 320, 240);
this->m_QTBackGroundItem->setPixmap ( *this->m_QTBackGroundPixmap );
this->m_QTGraphicsScene->addItem(this->m_QTBackGroundItem);
}CImageView::~CImageView( )
{
if(this->m_QTBackGroundPixmap) delete (this->m_QTBackGroundPixmap);
if(this->m_QTGraphicsScene) delete (this->m_QTGraphicsScene);
}void CImageView::dragEnterEvent(QDragEnterEvent event)
{
if (event->mimeData()->hasFormat("application/x-dnditemdata"))
{
switch( dynamic_cast<CQtShapesLabel>(event->source())->getType() )
{
case CQtShapesLabel::SPHERE:
cout << "SPHERE" << endl;
break;
case CQtShapesLabel::CUBE:
cout << "CUBOID" << endl;
break;
case CQtShapesLabel::CUBOID:
cout << "CUBOID" << endl;
break;
case CQtShapesLabel::CYLINDER:
cout << "CONE" << endl;
break;
case CQtShapesLabel::HEXAGONALPRISM:
cout << "PYRAMID" << endl;
break;
case CQtShapesLabel::CONE:
cout << "CONUS" << endl;
break;
case CQtShapesLabel::SQUAREBASEDPYRAMID:
cout << "CYLINDER" << endl;
break;
case CQtShapesLabel::TRIANGULARBASEDPYRAMID:
cout << "SPHERE" << endl;
break;
case CQtShapesLabel::TRIANGULARPRISM:
cout << "SPHERE" << endl;
break;
case CQtShapesLabel::CIRCLE:
cout << "CIRCLE" << endl;
break;
case CQtShapesLabel::OVAL:
cout << "OVAL" << endl;
break;
case CQtShapesLabel::TRIANGLE:
cout << "TRIANGLE" << endl;
break;
case CQtShapesLabel::SQUARE:
cout << "SQUARE" << endl;
break;
case CQtShapesLabel::RECTANGLE:
cout << "RECTANGLE" << endl;
break;
case CQtShapesLabel::RHOMBUS:
cout << "RHOMBUS" << endl;
break;
case CQtShapesLabel::TRAPEZOID:
cout << "TRAPEZOID" << endl;
break;
case CQtShapesLabel::SHAPE3D:
default:
event->ignore();
break;
}
}
else
{
event->ignore();
}
}void CImageView::dragMoveEvent(QDragMoveEvent *event)
{
if (event->mimeData()->hasFormat("application/x-dnditemdata"))
{
event->accept();
int aaa = 9999;
cout << aaa << endl;
} else
{
event->ignore();
}
}void CImageView::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat("application/x-dnditemdata"))
{
event->accept();
int aaa = 44444444;
cout << aaa << endl;
} else
{
event->ignore();
}
}
@ -
Hi, thank you for your reply. I don't want to drag and drop a QWidget, but I want to draw a shape onto QGraphicsView when I drop the QLabel on the QGraphicsView. And I'm expecting the shape to be able to be modified/changed after a further drag within the QGraphicsView.
Any demos?
Cheers
Pei[quote author="Code_ReaQtor" date="1362479727"]Sorry but it is not really clear how you implemented receiving the "drops" - you only show what was in the header file of your subclassed QGraphicsView.
Anyways, if you actually want to drag and drop a QWidget (QLabel, etc) into a QGraphicsView/Scene, you need to use "QGraphicsProxyWidget":http://qt-project.org/doc/qt-4.8/qgraphicsproxywidget.html
Also, some devs, most of the time, forgets to enable "setAcceptDrops":http://doc-snapshot.qt-project.org/4.8/qwidget.html#acceptDrops-prop[/quote]
[quote author="Code_ReaQtor" date="1362479727"]Sorry but it is not really clear how you implemented receiving the "drops" - you only show what was in the header file of your subclassed QGraphicsView.
Anyways, if you actually want to drag and drop a QWidget (QLabel, etc) into a QGraphicsView/Scene, you need to use "QGraphicsProxyWidget":http://qt-project.org/doc/qt-4.8/qgraphicsproxywidget.html
Also, some devs, most of the time, forgets to enable "setAcceptDrops":http://doc-snapshot.qt-project.org/4.8/qwidget.html#acceptDrops-prop[/quote]
-
Hi,
I tested your aplication and it works as required. The problem is that in your dragEnterEvent() you are not using
event->accept() anywhere, try to add the same and run again. -
[quote author="jiapei100" date="1362553970"]
I don't want to drag and drop a QWidget, but I want to draw a shape onto QGraphicsView when I drop the QLabel on the QGraphicsView.
[/quote]When dropped, it should be changed into a QGraphicsItem.
I can't really see some major problems (or I am just missing something). Keep in mind to check the following using cout/qDebug/etc:
check if setAcceptDrops is set to true
check if "dynamic_cast" worked
are you using "enum" with these? CQtShapesLabel::SPHERE, CQtShapesLabel::CUBE, etc.... since I can't see them implemented in the code
-
You are right Sam... Thank you so much !!
[quote author="Sam" date="1362568332"]Hi,
I tested your aplication and it works as required. The problem is that in your dragEnterEvent() you are not using
event->accept() anywhere, try to add the same and run again.[/quote]
-
[quote author="jiapei100" date="1362607972"]
You are right Sam... Thank you so much !![quote author="Sam" date="1362568332"]Hi,
I tested your aplication and it works as required. The problem is that in your dragEnterEvent() you are not using
event->accept() anywhere, try to add the same and run again.[/quote]
[/quote]
You are welcome :)