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
Forum Updated to NodeBB v4.3 + New Features

QGraphicsScene item is drawn at twice(x2) position

Scheduled Pinned Locked Moved Solved General and Desktop
qgraphicsscenescenepos
3 Posts 1 Posters 741 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