c++qtqt5qgraphicsviewqmouseevent

qt get mouse clicked position relative to image in a graphics view


I want to allow user to draw lines on image using the mouse, I'm using graphics view and mouse event but the position I get is not the right position relative to the image here is the mouse event function

void InitializationDialog::mousePressEvent(QMouseEvent *event) {
    if(drawing) {
        points.append(event->pos());
        if(!points.isEmpty()) {
            if(points.size()==1) {
                QString fileName = list.at(choosed);
                QImage image(fileName);
                QGraphicsScene* scene = new QGraphicsScene();
                QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(image));
                scene->addItem(item);
                QColor color(255,0,0);
                QBrush brush(color);
                QPen pen(brush, 4);
                QGraphicsLineItem* line = new QGraphicsLineItem(points.at(0).x(),points.at(0).y(),points.at(0).x()+1,points.at(0).y()+1);
                line->setPen(pen);
                scene->addItem(line);

                ui->graphicsView->setScene(scene);
                return;
            }
        }
    }
}

That should draw a point (I'm replacing it with one-pixel long line to look like a point)

Now I get the red point far away the mouse click like shown in that image enter image description here

How can I make it exactly on the mouse cursor?

Edit:

I made a custom class for graphics scene to get the click relative to it, I tried overriding mouse pressed for graphics view but the scene is not the same size as graphics view and the point still away the mouse click

overriding mouse pressed in my custom scene didn't help much because I always get 0,0 position for clicking the scene no matter where I click

new files code:

header file

#ifndef INITGRAPH_H
#define INITGRAPH_H
#include <QtGui>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QPoint>
#include <QGraphicsSceneMouseEvent>
class InitGraph : public QGraphicsView {
    Q_OBJECT
public:
    InitGraph(QWidget *parent = 0);
    virtual ~InitGraph() {};
};

class CustomScene : public QGraphicsScene {
    Q_OBJECT
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
signals:
    void pressed(QPoint p);
};
#endif // INITGRAPH_H

the source file

#include "initgraph.h"
InitGraph::InitGraph(QWidget *parent):QGraphicsView(parent)
{
}
void CustomScene::mousePressEvent(QGraphicsSceneMouseEvent *event){
    qDebug(QString::number(event->pos().rx()).toLatin1());
    QPoint p = event->pos().toPoint();
    emit pressed(p);
}

Solution

  • If you want to add a QGraphicsLineItem you must use the system coordinates of the scene for this you must use the function the scenePos() method of QGraphicsSceneMouseEvent and the method mapFromScene() of the items.

    for this we must override the methods mousePressEvent, mouseMoveEvent and mouseReleaseEvent of QGraphicsScene, all of the above I implemented it in the following class:

    class CustomScene : public QGraphicsScene
    {
        Q_OBJECT
        QGraphicsLineItem *item;
    protected:
        void mousePressEvent(QGraphicsSceneMouseEvent *event){
    
            item = new QGraphicsLineItem;
            addItem(item);
            const QPointF p = event->scenePos();
    
            item->setPos(p);
        }
    
        void mouseMoveEvent(QGraphicsSceneMouseEvent *event){
            const QPointF p  =item->mapFromScene(event->scenePos());
            QLineF l = item->line();
            l.setP2(p);
            item->setLine(l);
        }
    
        void mouseReleaseEvent(QGraphicsSceneMouseEvent *event){
            const QPointF p  =item->mapFromScene(event->scenePos());
            QLineF l = item->line();
            l.setP2(p);
            item->setLine(l);
        }
    
    };
    

    The complete code is on the following link.