3

I have a class that inherits from QGraphicsView. I use a QGraphicsScene to display an image in a window.

Here it works properly. However, I would like to use the QGraphicsSceneMouseEvent mouse events to draw on this image. The problem is that if I use QGraphicsSceneMouseEvent I do not fit in the mousePressEvent and mouseMoveEvent methods.

I tried with QMouseEvent * event but I do not have access to lastScenePos () for example.

Here is my code that displays the image

DisplayImage.h :

class DisplayImage : public QGraphicsView{

Q_OBJECT

public:
DisplayImage(QWidget *parent=0);
void displayImg(const QImage &image);

private:
QGraphicsScene *scene;
QPixmap pixmap;
QGraphicsPixmapItem *pixmapItem;

protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
};

DisplayImage.cpp:

DisplayImage::DisplayImage(QWidget* parent) : QGraphicsView(parent){
scene = new QGraphicsScene(this);
pixmapItem=new QGraphicsPixmapItem(pixmap);
scene->addItem(pixmapItem);
this->setScene(scene);
}
void DisplayImage::displayImg(const QImage &image){
pixmap=QPixmap::fromImage(image);
pixmapItem->setPixmap(pixmap);
this->setSceneRect(0,0,image.width(),image.height());
this->fitInView(pixmapItem, Qt::KeepAspectRatio);
this->centerOn(pixmapItem);
}

here I would like to use the mousePressEvent and mouseMoveEvent methods with QGraphicsSceneMouseEvent. Would anyone have a solution to work around the problem?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241

1 Answers1

2

When you overwrite a method, you can not change the type of data indicated by the arguments. The solution is to use an eventfilter for the scene:

*.h

#ifndef DISPLAYIMAGE_H
#define DISPLAYIMAGE_H

#include <QGraphicsView>

class DisplayImage : public QGraphicsView
{
    Q_OBJECT
public:
    DisplayImage(QWidget *parent=0);
    void displayImg(const QImage &image);

    bool eventFilter(QObject *watched, QEvent *event);
private:
    QGraphicsScene *scene;
    QPixmap pixmap;
    QGraphicsPixmapItem *pixmapItem;
};
#endif // DISPLAYIMAGE_H

*.cpp

#include "displayimage.h"

#include <QEvent>
#include <QGraphicsPixmapItem>
#include <QGraphicsSceneMouseEvent>

#include <QDebug>

DisplayImage::DisplayImage(QWidget *parent):QGraphicsView(parent)
{
    scene = new QGraphicsScene(this);
    pixmapItem=new QGraphicsPixmapItem(pixmap);
    scene->addItem(pixmapItem);
    setScene(scene);
    scene->installEventFilter(this);
}

void DisplayImage::displayImg(const QImage &image){
    pixmap=QPixmap::fromImage(image);
    pixmapItem->setPixmap(pixmap);
    setSceneRect(image.rect());
    fitInView(pixmapItem, Qt::KeepAspectRatio);
    centerOn(pixmapItem);
}

bool DisplayImage::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == scene){
        // press event
        QGraphicsSceneMouseEvent *mouseSceneEvent;
        if(event->type() == QEvent::GraphicsSceneMousePress){
            mouseSceneEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
            qDebug()<<mouseSceneEvent->scenePos()<<mouseSceneEvent->lastScenePos();
           // your logic here
        }
        // move event
        else if (event->type() == QEvent::GraphicsSceneMouseMove) {
            mouseSceneEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
            qDebug()<<mouseSceneEvent->scenePos()<<mouseSceneEvent->lastScenePos();
            // your logic here
        }
        // release event
        else if (event->type() == QEvent::GraphicsSceneMouseRelease) {
            mouseSceneEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
            qDebug()<<mouseSceneEvent->scenePos()<<mouseSceneEvent->lastScenePos();
            // your logic here
        }
    }
    return QGraphicsView::eventFilter(watched, event);
}

The complete example can be downloaded from the following link

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thank you for your answer, for cons I do not see how to use the methods mousePressEvent and mouseMoveEvent? I put the code I want directly in the eventfilter? or do I rewrite both methods? Because when I just do eventfilter, I do not see the debug appear ... –  Jul 03 '18 at 12:33
  • @Tom13000 Have you put the following `return QGraphicsView::eventFilter(watched, event);`? Have you modified something to my solution? – eyllanesc Jul 03 '18 at 12:34
  • @Tom13000 you must use `void mouseXXXEvent(QMouseEvent *event)` – eyllanesc Jul 03 '18 at 12:37
  • I used exactly your solution to evenfilter with the return. Then I used mousePressEvent (QMouseEvent * event) and mouseMoveEvent (QMouseEvent * event) with my code but if I put a debug in these methods there is nothing that appears. –  Jul 03 '18 at 12:44
  • For example, for the mouseMoveEvent method (QMouseEvent * event), I have compilation errors with event-> lastScenePos () and event-> scenePos () –  Jul 03 '18 at 12:47
  • @Tom13000 Have you called the parent's constructor `void DisplayImage::mouseXXXEvent(QMouseEvent *event) {... QGraphicsView::mouseXXXEvent(event); }`? – eyllanesc Jul 03 '18 at 12:48
  • @Tom13000 Are you using my example or are you adapting my code to your project? – eyllanesc Jul 03 '18 at 12:48
  • @Tom13000 QMouseEvent does not have a scenePos() method. that is why I propose to use the eventFilter. – eyllanesc Jul 03 '18 at 12:51
  • ok but in this case, how can I call eventfilter in the method mouseMoveEvent (QMouseEvent * event). Because it was this problem that I had. Otherwise yes I call the methods void DisplayImage :: mouseMoveEvent (QMouseEvent * event) –  Jul 03 '18 at 12:56
  • @Tom13000 I do not understand, what you asked is how to use the event QGraphicsSceneMouseEvent in QGraphicsView, and I answered that you can not do it using mousePressEvent, if you want to use events you should use an event filter. Have you tried my example ?, in conclusion forget about mousePressEvent and mouseMoveEvent, implement your logic inside eventFilter. – eyllanesc Jul 03 '18 at 12:58
  • @Tom13000 QGraphicsSceneMouseEvent is not an event of QGraphicsView but of QGraphicsScene. What my solution proposes is to listen to those events from QGraphicsView. In conclusion eventFilter helps you analyze events from other QObjects without the need to inherit from the class. – eyllanesc Jul 03 '18 at 13:02
  • I'm sorry for making you waste your time. Your solution was correct from the beginning but I did not install eventfilter in my constructor ....its work!!! –  Jul 03 '18 at 13:08
  • 1
    @Tom13000 If someone offers you an example, it is for you to test it, and when you see that it works and you understand how it works, you should try to implement it in your own code, you must be ordered. – eyllanesc Jul 03 '18 at 13:10