Search code examples
c++qtdrag-and-dropqt5qgraphicsview

QGraphicsPixmapItem doesn't show in QGraphicsView


I subclassed QGraphicsView (class Display) and implemented drag and drop from a QTableView. The QGraphicsScene has in it preexisting items and the scene()->itemsBoundingRect covers the entire earth. If I artificially set the QGraphicsPixmapItem's boundingRect to the viewPort() of the QGraphicsView, I don't see the QPixmap I set in the QGraphicsPixmapItem and added to the scene(). If I fitInView the scene()->itemsBoundingRect, the pixmap is dropped on the whole world. I would like it dropped on my viewport, but essentially fitInView viewPort doesn't show the item, even though according to debug it's visible and notObscured().

void Display::dragEnterEvent(QDragEnterEvent* event)
{

    event->acceptProposedAction();
    update();
}

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

  void TableView::mouseMoveEvent(QMouseEvent *event)
    {
        QDrag* drag = new QDrag(this);
        QMimeData *mime = new QMimeData();
        drag->setMimeData(mime);
        QImage image("/Users/sb/Downloads/puffin.jpeg");
        mime->setImageData(image);
        drag->setPixmap(QPixmap::fromImage(image).scaled(10,10));
        drag->exec();
        QTableView::mouseMoveEvent(event);

}

Edited to try @Eyllanesc suggestion

void Display::dropEvent(QDropEvent* event)
{

    setCacheMode(QGraphicsView::CacheBackground);
    setViewportUpdateMode(QGraphicsView::FullViewportUpdate);

    if(event->mimeData()->hasImage())
    {
        pixMap = qvariant_cast<QPixmap>(event->mimeData()->imageData());
        pixMap = pixMap.scaledToHeight(10);
        pixMap = pixMap.scaledToWidth(10);
        bool h = pixMap.isNull(); //returns false

        posn = mapToScene(event->pos());

        QRectF ff  = mapToScene(viewport()->geometry()).boundingRect();
        bool ps = ff.contains(posn); //returns true

        item = new QGraphicsPixmapItem(pixMap);
        scene()->addItem(item);

        item->setPos( posn);
        item->setZValue(100);
        item->setVisible(true);
        item->setOpacity(1.0);
        item->update();
        scene()->update();
        auto lView = qobject_cast<QGraphicsView*>(this);
        lView->fitInView(ff, Qt::KeepAspectRatio);// no pixmap is shown
        invalidateScene(ff);
        bool i = item->isObscured(); //returns false
        repaint();
        update();
    }
    event->acceptProposedAction();

}

-


Solution

  • In the next part I show you a working example of how to implement drag-and-drop from a QTableView to a QGraphicsView:

    #include <QApplication>
    #include <QDrag>
    #include <QGraphicsView>
    #include <QHBoxLayout>
    #include <QMimeData>
    #include <QMouseEvent>
    #include <QTableView>
    #include <QGraphicsPixmapItem>
    #include <random>
    #include <QStandardItemModel>
    
    
    static std::random_device rd;
    static std::mt19937 rng(rd());
    
    
    class TableView: public QTableView{
    public:
        using QTableView::QTableView;
    protected:
        void mousePressEvent(QMouseEvent *event){
            if (event->button() == Qt::LeftButton)
                dragStartPosition = event->pos();
        }
        void mouseMoveEvent(QMouseEvent *event){
            if (!(event->buttons() & Qt::LeftButton))
                return;
            if ((event->pos() - dragStartPosition).manhattanLength()
                    < QApplication::startDragDistance())
                return;
    
            QDrag *drag = new QDrag(this);
            QMimeData *mimeData = new QMimeData;
    
            // create image
            QImage image(100, 100, QImage::Format_RGB32);
            std::uniform_int_distribution<int> uni(0, 255);
            image.fill(QColor(uni(rng), uni(rng), uni(rng)));
    
            mimeData->setImageData(image);
            drag->setPixmap(QPixmap::fromImage(image).scaled(10,10));
            drag->setMimeData(mimeData);
    
            drag->exec();
            QTableView::mouseMoveEvent(event);
        }
    private:
        QPoint dragStartPosition;
    };
    
    class Display: public QGraphicsView{
    public:
        using QGraphicsView::QGraphicsView;
    protected:
        void dragMoveEvent(QDragMoveEvent *event){
            if(event->mimeData()->hasFormat("application/x-qt-image"))
                event->acceptProposedAction();
        }
    
        void dropEvent(QDropEvent *event){
            if (event->source() == this)
                return;
            QPixmap pixmap = qvariant_cast<QPixmap>(event->mimeData()->imageData());
            QGraphicsPixmapItem *pixmap_item = scene()->addPixmap(pixmap);
            pixmap_item->setPos(mapToScene(event->pos()));
            event->acceptProposedAction();
        }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QWidget w;
        QHBoxLayout* lay = new QHBoxLayout(&w);
        QGraphicsScene scene;
        Display view(&scene);
        view.setAcceptDrops(true);
        TableView table;
        QStandardItemModel model(10, 10);
        table.setModel(&model);
        lay->addWidget(&table);
        lay->addWidget(&view);
        w.show();
    
        return a.exec();
    }
    

    enter image description here