如何在鼠标下方的QGraphicsView上正确放置小部件?

问题描述

Following my previous post我一直在尝试使用QGraphicsView解决定位问题。

将小部件从QListWidget拖放到QGraphicsView内后,它会跳转到任何地方。

re

问题,我也在其他用户的帮助下尝试解决以下问题: 将小部件拖到QGraphicsView内并放下。它只是在随机位置出现,必须注意检索它。此行为对用户不友好,有时需要花费一些时间才能找到小部件。

代码下方:

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,QPen(Qt::black),QBrush(Qt::darkGreen));
            auto *sizegrip = new QSizegrip(wgt);
            auto *layout = new QHBoxLayout(wgt);

            layout->setContentsMargins(0,0);
            layout->addWidget(sizegrip,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));
        }
    }
}

迄今为止已尝试解决的问题:

现在QGraphicsScene已被子类化以重写鼠标事件,尤其是在这种情况下,注意dropEvent(QGraphicsSceneDragDropEvent *event)是因为它是“查看窗口小部件”的负责功能。 / p>

进行了多次试验和错误,并且在相同功能下尝试添加以下部分:

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,QBrush(Qt::darkGreen));
        auto *sizegrip = new QSizegrip(wgt);
        auto *layout = new QHBoxLayout(wgt);
}

尝试进行的另一件事是提供QPointevent->scenePos().toPoint(),以达到目标,但不幸的是,这也不能解决问题:

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,QBrush(Qt::darkGreen));
        auto *sizegrip = new QSizegrip(wgt);
        auto *layout = new QHBoxLayout(wgt);
} 

如果有人对问题可能有什么想法,请提供如何解决问题的指导。

解决方法

  1. proxy->setPos(initPos.x(),initPos.y() + proxyControl->rect().height());更改为proxy->setPos(10,10);

  2. 设置场景矩形:

     Scene::Scene(QObject *parent) :
         QGraphicsScene(parent)
     {
         setBackgroundBrush(Qt::lightGray);
         setSceneRect(0,1000,1000);
     }
    
  3. 设置视图对齐方式,例如在 MainWindow.cpp 中:

     ui->graphicsView->setAlignment(Qt::AlignLeft | Qt::AlignTop);