Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QGraphicsScene item is drawn at twice(x2) position

QGraphicsScene item is drawn at twice(x2) position

Scheduled Pinned Locked Moved Solved General and Desktop
qgraphicsscenescenepos
3 Posts 1 Posters 877 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    bliako
    wrote on last edited by
    #1

    In the following code I am creating a custom widget which has a subclass of QGraphicsScene embeded in it. My aim is to click and add a point to the scene. A point is my subclass of QGraphicsItem. I want to move that point around and later connect it to other points and make a spline path. The problem I am facing is that the point is not drawn at where I click but at a place which is form by doubling the mouse-event's scenePos() coordinates. So if I click at (100,100) the point is drawn at (200,200). I suspect that I have misunderstood the coordinate system despite reading the documentation. So I am asking additionally to point me to some simple-to-digest advice on how the widgets placement works. My example code follows:

    /* use the following pro:
    QT += widgets core gui
    
    CONFIG += debug console
    SOURCES = example.cpp
    TARGET = example
    */
    #include <QGraphicsItem>
    #include <QPainter>
    #include <QWidget>
    #include <QRectF>
    #include <QPointF>
    #include <QGraphicsScene>
    #include <QStyleOptionGraphicsItem>
    #include <QGraphicsSceneMouseEvent>
    #include <QKeyEvent>
    #include <QGraphicsView>
    #include <QApplication>
    #include <QOpenGLWidget>
    #include <QMainWindow>
    #include <QGridLayout>
    #include <QDebug>
    
    class GIPoint : public QGraphicsItem{
    public:
    	GIPoint(QGraphicsItem * parent, const QPointF &position);
    protected:
    	QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
    	QRectF boundingRect() const override;
    	void paint(
    		QPainter *painter,
    		const QStyleOptionGraphicsItem *option,
    		QWidget *widget
    	);
    };
    class GraphicsSceneWidget : public QGraphicsScene {
    
    public:
    	explicit GraphicsSceneWidget(QObject *parent);
    	~GraphicsSceneWidget();
    	virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
    };
    
    class VectorGraphicsWidget : public QWidget {
    public:
    	VectorGraphicsWidget(QWidget *parent);
    	~VectorGraphicsWidget();
    private:
    	GraphicsSceneWidget *myGraphicsSceneWidget;
    };
    
    // implementation
    GIPoint::GIPoint(
    	QGraphicsItem *parent,
    	const QPointF &position
    ) : QGraphicsItem(parent) {
    	setFlag(QGraphicsItem::ItemIsMovable, true);
    	setFlag(QGraphicsItem::ItemIsSelectable, true);
    	setPos(position);
    	qWarning() << "GIPoint::GIPoint() : init at " << position;
    }
    QVariant GIPoint::itemChange(
    	GraphicsItemChange change,
    	const QVariant &value
    ){
    	if (change == QGraphicsItem::ItemPositionChange) {
    		qWarning("position changed");
    	}
    	return value;
    }
    QRectF GIPoint::boundingRect() const {
    	return QRectF(pos().x(), pos().y(), 5, 5);
    //	return QRectF(0,0, 5, 5);
    }
    void GIPoint::paint(
    	QPainter *painter,
    	const QStyleOptionGraphicsItem *option,
    	QWidget *widget
    ){
    	(void )option;
    	(void )widget;
    	QPointF xx = scenePos();
    	QRectF rect = QRectF(xx.x(), xx.y(), 10, 10);
    	qWarning() << "painting: scenePos " << scenePos() << ", rect " << rect;
    	QBrush brush = QBrush(Qt::black, Qt::SolidPattern);
    	//painter->fillRect(rect, brush);
    	painter->drawRect(rect);
    }
    
    GraphicsSceneWidget::GraphicsSceneWidget(QObject *parent)
    	: QGraphicsScene(parent)
    {}
    GraphicsSceneWidget::~GraphicsSceneWidget(){}
    void GraphicsSceneWidget::mousePressEvent(
    	QGraphicsSceneMouseEvent *event
    ){
    	GIPoint *gip = new GIPoint(Q_NULLPTR, event->scenePos());
    	addItem(gip);
    	QGraphicsScene::mousePressEvent(event);
    }
    	
    VectorGraphicsWidget::VectorGraphicsWidget(QWidget *parent) :
    	QWidget(parent)
    {
    	myGraphicsSceneWidget = new GraphicsSceneWidget(this);
    	QGraphicsView *view = new QGraphicsView(myGraphicsSceneWidget);
    	myGraphicsSceneWidget->setSceneRect(QRectF(0, 0, 500, 500));
    	QGridLayout *centralLayout = new QGridLayout;
    	centralLayout->addWidget(view);
    	setLayout(centralLayout);
    	myGraphicsSceneWidget->addRect(
    		QRectF(0, 0, 100, 100),
    		QPen(Qt::black),
    		QBrush(Qt::green)
    	);
    	view->show();
    }
    VectorGraphicsWidget::~VectorGraphicsWidget() {
    	delete myGraphicsSceneWidget;
    }
    int main(int argc, char **argv){
    	QApplication app(argc, argv);
    	app.setApplicationName("test");
    	app.setOrganizationName("myorg");
    	app.setOrganizationDomain("myorg.com");
    
    	QMainWindow *w = new QMainWindow();
    	w->resize(500, 500);
    	w->setCentralWidget(new VectorGraphicsWidget(Q_NULLPTR));
    	w->show();
     
    	return app.exec();
    }
    
    
    B 1 Reply Last reply
    0
    • B Offline
      B Offline
      bliako
      wrote on last edited by bliako
      #3

      I have just figured it out.

      My first misunderstanding was that the boundingRect()'s coordinates must be (-0.5,-0.5) which means they are relative to the current item's position and not absolute on the Scene. and so this is the correct one:

      QRectF GIPoint::boundingRect() const {
      //	return QRectF(pos().x(), pos().y(), 5, 5);
      	return QRectF(-0.5, -0.5, 5, 5);
      }
      

      My second misunderstanding was in paint(). Do not use the pos() or scenePos() coordinates in order to draw the item. Instead draw it at (0,0). So the corrected paint() is this:

      void GIPoint::paint(
              QPainter *painter,
              const QStyleOptionGraphicsItem *option,
              QWidget *widget
      ){
              (void )option;
              (void )widget;
              QRectF rect = boundingRect();
              qWarning() << "painting: scenePos " << scenePos() << ", rect " << rect;
              QBrush brush = QBrush(Qt::black, Qt::SolidPattern);
              painter->fillRect(rect, brush);  
              //painter->drawRect(rect); 
      }
      

      The original program in my question still needs to be modified. Or shall I edit the changes in?

      1 Reply Last reply
      1
      • B bliako

        In the following code I am creating a custom widget which has a subclass of QGraphicsScene embeded in it. My aim is to click and add a point to the scene. A point is my subclass of QGraphicsItem. I want to move that point around and later connect it to other points and make a spline path. The problem I am facing is that the point is not drawn at where I click but at a place which is form by doubling the mouse-event's scenePos() coordinates. So if I click at (100,100) the point is drawn at (200,200). I suspect that I have misunderstood the coordinate system despite reading the documentation. So I am asking additionally to point me to some simple-to-digest advice on how the widgets placement works. My example code follows:

        /* use the following pro:
        QT += widgets core gui
        
        CONFIG += debug console
        SOURCES = example.cpp
        TARGET = example
        */
        #include <QGraphicsItem>
        #include <QPainter>
        #include <QWidget>
        #include <QRectF>
        #include <QPointF>
        #include <QGraphicsScene>
        #include <QStyleOptionGraphicsItem>
        #include <QGraphicsSceneMouseEvent>
        #include <QKeyEvent>
        #include <QGraphicsView>
        #include <QApplication>
        #include <QOpenGLWidget>
        #include <QMainWindow>
        #include <QGridLayout>
        #include <QDebug>
        
        class GIPoint : public QGraphicsItem{
        public:
        	GIPoint(QGraphicsItem * parent, const QPointF &position);
        protected:
        	QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
        	QRectF boundingRect() const override;
        	void paint(
        		QPainter *painter,
        		const QStyleOptionGraphicsItem *option,
        		QWidget *widget
        	);
        };
        class GraphicsSceneWidget : public QGraphicsScene {
        
        public:
        	explicit GraphicsSceneWidget(QObject *parent);
        	~GraphicsSceneWidget();
        	virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
        };
        
        class VectorGraphicsWidget : public QWidget {
        public:
        	VectorGraphicsWidget(QWidget *parent);
        	~VectorGraphicsWidget();
        private:
        	GraphicsSceneWidget *myGraphicsSceneWidget;
        };
        
        // implementation
        GIPoint::GIPoint(
        	QGraphicsItem *parent,
        	const QPointF &position
        ) : QGraphicsItem(parent) {
        	setFlag(QGraphicsItem::ItemIsMovable, true);
        	setFlag(QGraphicsItem::ItemIsSelectable, true);
        	setPos(position);
        	qWarning() << "GIPoint::GIPoint() : init at " << position;
        }
        QVariant GIPoint::itemChange(
        	GraphicsItemChange change,
        	const QVariant &value
        ){
        	if (change == QGraphicsItem::ItemPositionChange) {
        		qWarning("position changed");
        	}
        	return value;
        }
        QRectF GIPoint::boundingRect() const {
        	return QRectF(pos().x(), pos().y(), 5, 5);
        //	return QRectF(0,0, 5, 5);
        }
        void GIPoint::paint(
        	QPainter *painter,
        	const QStyleOptionGraphicsItem *option,
        	QWidget *widget
        ){
        	(void )option;
        	(void )widget;
        	QPointF xx = scenePos();
        	QRectF rect = QRectF(xx.x(), xx.y(), 10, 10);
        	qWarning() << "painting: scenePos " << scenePos() << ", rect " << rect;
        	QBrush brush = QBrush(Qt::black, Qt::SolidPattern);
        	//painter->fillRect(rect, brush);
        	painter->drawRect(rect);
        }
        
        GraphicsSceneWidget::GraphicsSceneWidget(QObject *parent)
        	: QGraphicsScene(parent)
        {}
        GraphicsSceneWidget::~GraphicsSceneWidget(){}
        void GraphicsSceneWidget::mousePressEvent(
        	QGraphicsSceneMouseEvent *event
        ){
        	GIPoint *gip = new GIPoint(Q_NULLPTR, event->scenePos());
        	addItem(gip);
        	QGraphicsScene::mousePressEvent(event);
        }
        	
        VectorGraphicsWidget::VectorGraphicsWidget(QWidget *parent) :
        	QWidget(parent)
        {
        	myGraphicsSceneWidget = new GraphicsSceneWidget(this);
        	QGraphicsView *view = new QGraphicsView(myGraphicsSceneWidget);
        	myGraphicsSceneWidget->setSceneRect(QRectF(0, 0, 500, 500));
        	QGridLayout *centralLayout = new QGridLayout;
        	centralLayout->addWidget(view);
        	setLayout(centralLayout);
        	myGraphicsSceneWidget->addRect(
        		QRectF(0, 0, 100, 100),
        		QPen(Qt::black),
        		QBrush(Qt::green)
        	);
        	view->show();
        }
        VectorGraphicsWidget::~VectorGraphicsWidget() {
        	delete myGraphicsSceneWidget;
        }
        int main(int argc, char **argv){
        	QApplication app(argc, argv);
        	app.setApplicationName("test");
        	app.setOrganizationName("myorg");
        	app.setOrganizationDomain("myorg.com");
        
        	QMainWindow *w = new QMainWindow();
        	w->resize(500, 500);
        	w->setCentralWidget(new VectorGraphicsWidget(Q_NULLPTR));
        	w->show();
         
        	return app.exec();
        }
        
        
        B Offline
        B Offline
        bliako
        wrote on last edited by
        #2

        I have also crossposted this same question at https://stackoverflow.com/questions/57118393/qgraphicsscene-item-is-drawn-at-twicex2-position

        1 Reply Last reply
        0
        • B Offline
          B Offline
          bliako
          wrote on last edited by bliako
          #3

          I have just figured it out.

          My first misunderstanding was that the boundingRect()'s coordinates must be (-0.5,-0.5) which means they are relative to the current item's position and not absolute on the Scene. and so this is the correct one:

          QRectF GIPoint::boundingRect() const {
          //	return QRectF(pos().x(), pos().y(), 5, 5);
          	return QRectF(-0.5, -0.5, 5, 5);
          }
          

          My second misunderstanding was in paint(). Do not use the pos() or scenePos() coordinates in order to draw the item. Instead draw it at (0,0). So the corrected paint() is this:

          void GIPoint::paint(
                  QPainter *painter,
                  const QStyleOptionGraphicsItem *option,
                  QWidget *widget
          ){
                  (void )option;
                  (void )widget;
                  QRectF rect = boundingRect();
                  qWarning() << "painting: scenePos " << scenePos() << ", rect " << rect;
                  QBrush brush = QBrush(Qt::black, Qt::SolidPattern);
                  painter->fillRect(rect, brush);  
                  //painter->drawRect(rect); 
          }
          

          The original program in my question still needs to be modified. Or shall I edit the changes in?

          1 Reply Last reply
          1

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved