[solved]Drag and drop between two QGraphicViews in single widget



  • Hi all,
    I have a problem would like to have your guidance, as i am struggling to find the reason for it. I am basically having a widget with 2 QGraphicViews which are created using QT Designer 2.8.0 and QT 4.8.4. I am trying to implement the drag and drop between them and a QListWidget which is also there in the same Widget. I have implemented this:
    @
    GVIEW.CPP

    #include "gview.h"
    #include<QPixmapCache>

    #include<QGraphicsPixmapItem>
    #include <QtGui>

    gview::gview(QWidget *parent)
    : QGraphicsView(parent)
    {
    setMinimumSize(200, 200);
    setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
    setAlignment(Qt::AlignCenter);
    setAcceptDrops(true);
    setAutoFillBackground(true);
    clear();

    }

    void gview::dragEnterEvent(QDragEnterEvent *event)
    {
    //s setText(tr("<drop content>"));
    setBackgroundRole(QPalette::Highlight);

    event->acceptProposedAction();
    emit changed(event->mimeData());
    

    }

    void gview::dragMoveEvent(QDragMoveEvent *event)
    {
    event->acceptProposedAction();
    }
    void gview::dropEvent(QDropEvent *event)
    {
    const QMimeData *mimeData = event->mimeData();

    if (mimeData->hasImage()) {
    item->setPixmap(qvariant_cast<QPixmap>(mimeData->imageData()));
    } else if (mimeData->hasHtml()) {
        //setText(mimeData->html());
        //setTextFormat(Qt::RichText);
    } else if (mimeData->hasText()) {
        //setText(mimeData->text());
        //setTextFormat(Qt::PlainText);
    } else if (mimeData->hasUrls()) {
        QList<QUrl> urlList = mimeData->urls();
        QString text;
        for (int i = 0; i < urlList.size() && i < 32; ++i) {
            QString url = urlList.at(i).path();
            text += url + QString("\n");
        }
        //setText(text);
    } else {
        //setText(tr("Cannot display data"));
    }
    setBackgroundRole(QPalette::Dark);
    event->acceptProposedAction();
    

    }

    void gview::dragLeaveEvent(QDragLeaveEvent *event)
    {
    clear();
    event->accept();
    }

    void gview::clear()
    {
    // setText(tr("<drop content>"));
    setBackgroundRole(QPalette::Dark);

    emit changed();
    

    }

    GVIEW.H

    #ifndef GVIEW_H
    #define GVIEW_H

    #include <QWidget>
    #include <QGraphicsView>

    QT_BEGIN_NAMESPACE
    class QMimeData;
    QT_END_NAMESPACE

    class gview : public QGraphicsView
    {
    Q_OBJECT
    public:
    explicit gview(QWidget *parent = 0);
    QGraphicsPixmapItem *item;

    public slots:
    void clear();

    signals:
    void changed(const QMimeData *mimeData = 0);

    protected:
    void dragEnterEvent(QDragEnterEvent *event);
    void dragMoveEvent(QDragMoveEvent *event);
    void dragLeaveEvent(QDragLeaveEvent *event);
    void dropEvent(QDropEvent *event);
    };

    #endif // GVIEW_H

    @

    I think the problem is with @ item->setPixmap(qvariant_cast<QPixmap>(mimeData->imageData())); @

    I get no error during build or runtime, but image is not getting displayed in the QGraphicsView when i drag and drop the image on it.

    My Widget.cpp

    @
    #include "widget.h"
    #include "ui_widget.h"
    #include"gview.h"

    Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
    {
    ui->setupUi(this);
    ui->listWidget->setDragEnabled(true);
    // QGraphicsScene scn = new QGraphicsScene(ui->graphicsView);
    // QPixmap pix("
    .jpg *.png");
    //ui->graphicsView->setScene(scn);
    //scn->addPixmap(pix);
    ui->graphicsView->show();
    //ui->graphicsView->setAcceptDrops(true);
    //ui->graphicsView2->setAcceptDrops(true);
    ui->graphicsView2->show();

    }

    Widget::~Widget()
    {
    delete ui;
    }

    void Widget::on_pushButton_clicked()
    {
    QStringList files = QFileDialog::getOpenFileNames(this, tr("Select Images"),
    ":/Users/venkateshpadmanabhan/Desktop/");
    ui->listWidget->addItems(files);
    }

    void Widget::on_horizontalSlider_sliderMoved(int position)
    {
    QMatrix matrix;
    matrix.scale( position, 1.0); // zoom is zoom factor ( example: 1.1 is 110%)
    ui->graphicsView->setMatrix(matrix);
    }
    void Widget::on_dial_sliderMoved(int position)
    {
    QMatrix matrix1;
    matrix1.rotate(position*5);
    ui->graphicsView->setMatrix(matrix1);
    }

    @


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Please enclose your code with coding tags (an @ at the beginning and one at the end) This will make it readable.

    The error is the following: you are calling setPixmap on your QGraphicsView, but QGraphicsView doesn't have this method. You would need to add a QGraphicsPixmapItem to your view and set the pixmap on that item.

    Hope it helps



  • Hi SGaist,

    Thanks for your valuable reply, after getting the error i tried using

    QImage instead.. like

    @ if (mimeData->hasImage()) {
    QImage image = qvariant_cast<QImage>(mimeData->imageData()); @

    Yet, the image is not displayed in the QGraphicsView when i drag one. It just remains blank. I do not get any error too.. Could you show lights on this problem.

    Regards
    Venkatesh


  • Lifetime Qt Champion

    QImage doesn't display in image, it's only a container.

    Like I said before, if you want to drop that image on you view, you have to create a QGraphicsPixmapItem and set the image on it.



  • Hi,
    Thanks for your valuable response. I am trying to do it, but with less success. I know i am making a mistake, but couldn't understand what exactly. It would be great to have your guidance

    @ QGraphicsPixmapItem *item = new QGraphicsPixmapItem(); @
    

    This was how i thought of creating the item. But i am getting errors like

    @ /Library/Frameworks/QtGui.framework/Headers/qpixmap.h:77: candidate constructor not viable: no known conversion from 'QImage' to 'const QSize &' for 1st argument
    QPixmap(const QSize &); @

    My coding line is @ item->setPixmap(qvariant_cast<QImage>(mimeData->imageData())); @

    Sorry for my ignorance.
    ^


  • Lifetime Qt Champion

    The error is pretty clear, you need to provide a QPixmap not a QImage.

    Use QPixmap::fromImage



  • Hi,

    Thank you so much for reply again. I just did as per your suggestion but again i get an error. This time with the qvariant_cast :

    @ item->setPixmap(qvariant_castQPixmap::fromImage(mimeData->imageData())); @

    The error message :

    @ /Users/venkateshpadmanabhan/Desktop/QT Implementation/Mainwindow/gview.cpp:35: error: no matching function for call to 'qvariant_cast'
    item->setPixmap(qvariant_castQPixmap::fromImage(mimeData->imageData()));
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /Library/Frameworks/QtCore.framework/Headers/qvariant.h:571: candidate template ignored: invalid explicitly-specified argument for template parameter 'T'
    template<typename T> inline T qvariant_cast(const QVariant &v) @

    But if i just use the QPixmap without "::fromImage", the image is not getting loaded, but i am able to run the application.

    Awaiting your kind support.

    Thanks and regards,
    Venkatesh


  • Lifetime Qt Champion

    Please, read the documentation...

    @QPixmap pixmap = QPixmap::fromimage(qvariant_cast<QImage>(mimeData->imageData()));@



  • Hi,

    Thanks again. I have implemented it. Yet i don't get any result. The QGraphicsView doesn't show any image which is dropped into it. It would be great help if you could implement the code and check whats the problem. As i am trying to check it but without any result as i dont get any error. But just the images are not displayed when dropped into the QGraphicsView. Awaiting your further guidance.

    Thanks and regards
    Venkatesh Padmanabhan


  • Lifetime Qt Champion

    Did you add the QGraphicsPixmapItem to the scene ?
    Did you move it to a visible position ?



  • Hi,
    Yeah i have actually promoted the class to the QGraphicsView created using QTCreator.

    @

    #include "gview.h"
    #include<QGraphicsPixmapItem>
    #include <QtGui>

    gview::gview(QWidget *parent)
    : QGraphicsView(parent)
    {
    setMinimumSize(200, 200);
    setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
    setAlignment(Qt::AlignCenter);
    setAcceptDrops(true);
    setAutoFillBackground(true);
    clear();

    }

    void gview::dragEnterEvent(QDragEnterEvent *event)
    {
    //s setText(tr("<drop content>"));
    setBackgroundRole(QPalette::Highlight);
    //const QMimeData *mimeData = event->mimeData();
    //if (mimeData->hasImage()) {
    // event->acceptProposedAction();
    // update();
    // } else {
    event->setAccepted(true);
    }

    //}

    void gview::dragMoveEvent(QDragMoveEvent *event)
    {
    event->acceptProposedAction();
    }

    void gview::dropEvent(QDropEvent *event)
    {
    const QMimeData *mimeData=event->mimeData();
    if(mimeData->hasImage()){
    QGraphicsView *v = new QGraphicsView();
    QGraphicsScene *scn = new QGraphicsScene(v);
    // QPixmap pixmap= QPixmap::fromImage(qvariant_cast<QImage>(mimeData->imageData()));
    // item->setPixmap(QPixmap::fromImage(qvariant_cast<QImage>(mimeData->imageData())));
    item->setPixmap(qvariant_cast<QPixmap>(mimeData->imageData()));
    scn->addItem(item);
    v->setScene(scn);
    v->show();
    // }
    //else if (mimeData->hasHtml()) {
    //s setText(mimeData->html());
    //s setTextFormat(Qt::RichText);
    // else if (mimeData->hasText()) {
    //s setText(mimeData->text());
    //s setTextFormat(Qt::PlainText);
    // else if (mimeData->hasUrls()) {
    // QList<QUrl> urlList = mimeData->urls();
    //QString text;
    //for (int i = 0; i < urlList.size() && i < 32; ++i) {
    // QString url = urlList.at(i).path();
    //text += url + QString("\n");
    //return(text);
    }
    //} else {
    //label->setText(tr("Cannot display data"));
    //event->setAccepted(false);
    //}
    //event->acceptProposedAction();

    //}
    void gview::dragLeaveEvent(QDragLeaveEvent *event)
    {
    // clear();
    event->accept();
    }

    void gview::clear()
    {
    // setText(tr("<drop content>"));
    // setBackgroundRole(QPalette::Dark);

    emit changed();
    

    }

    @

    Please do guide me whats going wrong here.


  • Lifetime Qt Champion

    You should not create a new scene and a new view each time you drop.
    Just set a scene on your view after you created it and add your new item to that scene.



  • Hi again,

    But how to access the graphicsView which is the object of the @Widget::ui->graphicsView@ This cannot be accessed directly as its from a non- static member. It would be great if you could provide me the code how to use it in another class gview, for setting the scene in this view @ graphicsView and graphicsView2 @ Both are QGraphicView created using QTDesigner

    Thanks and regards
    Venkatesh Padmanabhan


  • Lifetime Qt Champion

    Create the scenes in Widget's constructor and set them your graphics views using setScene and then access them in your drop event using the scene() function



  • Hi,
    Thanks for your valuable response. I have a problem, how to access the scenes declared in the constructor of WIDGET using scene() in drop event. I couldn't find a method to access those @ scn1 and scn @
    declared in Widget using @ scene() @


  • Lifetime Qt Champion

    You have to call it on the views you are implementing



  • I have created an object of class Widget in class gview to call upon @graphicsView1
    graphicsView2
    @ and created new scenes to accommodate it in gview, but it gets terminated when application starts to run.

    As you guided, how can I call upon the class using any other method?

    I have tried @

    Widget *wid = new Widget();
    wid->ui->scn1->additem(item);
    wid->ui->scn2->additem(item);
    update();

    @
    The item is the qgraphicspixmapitem, declared in gview as a pointer. I am not sure whether declaration is correct too

    @ QGraphicsPixmapItem *item; @

    And used it for the variant_cast. I am not sure what's the mistake I am doing, as the application terminates as soon as I drop the image into the view.



  • Hi SGaint,
    Atlast i was able to drag and drop the images into the qgraphicsview.

    I used
    @ scene()->setPixmap(pixmap); @

    Thank you so much for your wonderful guidance.

    Regards,
    Venkatesh Padmanabhan.


  • Lifetime Qt Champion

    You're welcome

    Don't forget to update the thread's title prepending solved so other forum users may know that a solution has been found :)



  • Hi,
    I would like to ask one more query related to the original post. I am able to drag and drop images into the view now. But it doesn't work with Url's from local file, if i want to drag an image from the desktop into QGraphicsView it doesn't work as i think it is passed as Url not as an image i hope. It would be great help if you could suggest how to cast an Url into QPixmap... Awaiting your response.


  • Lifetime Qt Champion

    I'd rather answer on your other "post":http://qt-project.org/forums/viewthread/31764/


Log in to reply
 

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