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_OBJECT

    public:

    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&#40;Qt::CopyAction | Qt::MoveAction, Qt::CopyAction&#41; == Qt::MoveAction)
        this->close();
    else
    {
        this->show();
        this->setPixmap(pixmap);
    }
    

    }@

    My inherited QGraphicsView class looks like:

    @class QTVIEWS_EXPORT CImageView : public QGraphicsView
    {
    Q_OBJECT

    protected:
    //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 view

    never responses. Why is it so? Can anybody help to explain please....

    Best Regards
    Pei


  • Lifetime Qt Champion

    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_OBJECT

    private:
    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 :)


Log in to reply
 

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