-1

Following my previous post I have been trying to solve a positioning problem withing a QGraphicsView.

After a widget is dragged from a QListWidget and dropped inside a QGraphicsView, it jumps everywhere.

re

The problem I have been trying to solve with also the help of another user is the following: As soon as the widget is dragged inside the QGraphicsView and dropped. It just goes in random locations and have to pay attention to retrieve it. This behavior is not user friendly and sometimes it takes a bit to locate the widget.

Below the code:

scene.h

#ifndef SCENE_H
#define SCENE_H

#include <QGraphicsScene>

class Scene : public QGraphicsScene
{
public:
    Scene(QObject *parent = nullptr);

protected:
  void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
  void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
  void dropEvent(QGraphicsSceneDragDropEvent *event);
};

#endif // SCENE_H

scene.cpp

void Scene::dropEvent(QGraphicsSceneDragDropEvent *event)
{
    QByteArray encoded =
            event->mimeData()->data("application/x-qabstractitemmodeldatalist");
    QDataStream stream(&encoded, QIODevice::ReadOnly);

    QStringList rosTables;
    QString newString;

    while (!stream.atEnd()) {
        int row, col;
        QMap<int, QVariant> roleDataMap;
        stream >> row >> col >> roleDataMap;
        rosTables << roleDataMap[Qt::DisplayRole].toString();
    }

    for (const QString &tableType : rosTables) {
        if (tableType == "Images") {
            QPoint initPos(0, 0);
            auto *wgt = new CustomTableWidget;
            auto *proxyControl = addRect(0, 0, 0, 0, QPen(Qt::black),
                                         QBrush(Qt::darkGreen));
            auto *sizeGrip = new QSizeGrip(wgt);
            auto *layout = new QHBoxLayout(wgt);

            layout->setContentsMargins(0, 0, 0, 0);
            layout->addWidget(sizeGrip, 0, Qt::AlignRight | Qt::AlignBottom);

            connect(wgt, &CustomTableWidget::sizeChanged, [wgt, proxyControl](){
                proxyControl->setRect(wgt->geometry().adjusted(-10, -10, 10, 10));
            });

            wgt->setColumnCount(2);
            wgt->setRowCount(2);

            for (int ridx = 0; ridx < wgt->rowCount(); ridx++) {
                for (int cidx = 0; cidx < wgt->columnCount(); cidx++) {
                    auto *item = new QTableWidgetItem();

                    item->setText(QString("%1").arg(ridx));
                    wgt->setItem(ridx,cidx,item);
                }
            }

            auto *const proxy = addWidget(wgt);


            proxy->setPos(initPos.x(), initPos.y()
                          + proxyControl->rect().height());
            proxy->setParentItem(proxyControl);

            proxyControl->setPos(initPos.x(), initPos.y());
            proxyControl->setFlag(QGraphicsItem::ItemIsMovable, true);
            proxyControl->setFlag(QGraphicsItem::ItemIsSelectable, true);
            proxyControl->setRect(wgt->geometry().adjusted(-10, -10, 10, 10));
        }
    }
}

What it was tried so far to solve the problem:

Now the QGraphicsScene have been subclassed to re-write the mouse events, in particular and in this case attention was given to the dropEvent(QGraphicsSceneDragDropEvent *event) as that is the responsible function to "see the widget"

Several trials and errors were conducted and in the same function it was tried to add the following part:

for (const QString &tableType : rosTables) {
    if (tableType == "Images") {
        QPoint initPos(event->scenePos()); // <-- Tried this but no change 
        auto *wgt = new CustomTableWidget;
        auto *proxyControl = addRect(0, 0, 0, 0, QPen(Qt::black),
                                     QBrush(Qt::darkGreen));
        auto *sizeGrip = new QSizeGrip(wgt);
        auto *layout = new QHBoxLayout(wgt);
}

An additional thing tried was to provide the QPoint the event->scenePos().toPoint() as deemed proper for the goal, but unfortunately that didn't solve the problem either:

for (const QString &tableType : rosTables) {
    if (tableType == "Images") {
        QPoint initPos(event->scenePos().toPoint()); // <-- Tried this too but no change
        auto *wgt = new CustomTableWidget;
        auto *proxyControl = addRect(0, 0, 0, 0, QPen(Qt::black),
                                     QBrush(Qt::darkGreen));
        auto *sizeGrip = new QSizeGrip(wgt);
        auto *layout = new QHBoxLayout(wgt);
} 

If anyone has an idea of what the problem might be please provide guidance on how to solve it.

scopchanov
  • 7,966
  • 10
  • 40
  • 68
Emanuele
  • 2,194
  • 6
  • 32
  • 71

1 Answers1

0
  1. Change proxy->setPos(initPos.x(), initPos.y() + proxyControl->rect().height()); to proxy->setPos(10, 10);.

  2. Set scene rect:

     Scene::Scene(QObject *parent) :
         QGraphicsScene(parent)
     {
         setBackgroundBrush(Qt::lightGray);
         setSceneRect(0, 0, 1000, 1000);
     }
    
  3. Set view alignment, e.g. in MainWindow.cpp:

     ui->graphicsView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    
scopchanov
  • 7,966
  • 10
  • 40
  • 68