Search code examples
c++qtqt5qgraphicssceneqgraphicsitem

Correct way to draw a QGraphicsItem on QGraphicsScene


I checked a couple of resources on qt's website and here but I could not solve my problem.

I'm trying to draw a rectangle on QGraphicsScene on mouse click and I want the new rectangle to be centered exactly where the user clicked but this does not work until the scene is big enough.

Here's what I tried

In MainWindow.cpp

MainWindow::MainWindow(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::MainWindow)
{
   ui->setupUi(this);
=
   ui->graphView->setContextMenuPolicy(Qt::CustomContextMenu);
   scene = new QGraphicsScene();
   ui->graphView->setScene(scene);
...
}


    void MainWindow::on_graphView_customContextMenuRequested(const QPoint &pos)
    {
     auto pp= ui->graphView->mapToScene(pos);
    tableOfRectangles.push_back( new component(pp,s,n,t)); //component is my class that inherits from qgraphicsitem
     scene->addItem(tableOfRectangles[tableOfRectangles.size()-1]);
    }

and in compenent.cpp

component::component(QPointF pos,unsigned int id, QString cname, QString ctype  )
{
    this->center = pos;
    this->id = id;
    this->name = cname;
    this->type = ctype;
    setFlag(ItemIsMovable);


}

QRectF component::boundingRect() const
{

    return QRectF(center.x(),center.y(),80,80);
}


My problem is:

The very first rectangles are drawn in the middle, and keep shifting slightly the more I add toward the correct position. Byadding more rectangles (or dragging the existing ones) making the scene big enough (when scroll bars start to appear), the new rectangles are added correctly at mouse position. but how do I do force them to be inserted at the correct position since the beginning?


Solution

  • You are combining the boundingRect coordinates that are relative to the item with the coordinates relative to the scene. On the other hand, don't complicate creating a custom item, instead use a custom QGraphicsRectItem. Finally it is recommended that you establish a sceneRect.

    component.h

    #ifndef COMPONENT_H
    #define COMPONENT_H
    
    #include <QGraphicsRectItem>
    
    class Component : public QGraphicsRectItem
    {
    public:
        Component(unsigned int id, QString cname, QString ctype, QGraphicsItem *parent=nullptr);
    private:
        unsigned int m_id;
        QString m_cname;
        QString m_ctype;
    };
    
    #endif // COMPONENT_H
    

    component.cpp

    #include "component.h"
    
    Component::Component(unsigned int id, QString cname, QString ctype, QGraphicsItem*parent):
        QGraphicsRectItem(parent), m_id(id), m_cname(cname), m_ctype(ctype)
    {
        setRect(-40, -40, 80, 80);
        setFlag(ItemIsMovable);
    }
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        ui->graphView->setContextMenuPolicy(Qt::CustomContextMenu);
        scene = new QGraphicsScene();
        ui->graphView->setScene(scene);
        ui->graphView->setSceneRect(QRect(0, 0, 400, 400));
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::on_graphView_customContextMenuRequested(const QPoint &pos)
    {
    
        QPointF pp = ui->graphView->mapToScene(pos);
        Component* component = new Component(s, n, t);
        scene->addItem(component);
        component->setPos(pp);
    }