0
votes

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();

}

-

1

1 Answers

1
votes

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