Search code examples
c++qtmouseeventcollisionqgraphicsitem

How to Set Mouse Collision Box for QGraphicsPixmapItem? [QT/C++]


When re-implementing any mouse event function in a QGraphicsPixmapItem such as mousePressEvent, mouseReleaseEvent, mouseMoveEvent, the graphics item uses pixel-perfect collision. For example, for the mousePressEvent to be triggered, the mouse must be exactly on top of a visible pixel in the pixmap when clicked.

On the other hand, I want the collision to be a generalized box based on the pixmap's width and height: [0, 0, width, height].

How can this be accomplished?

(Some sample code cause people seem to like that):

class MyGraphicsItem: public QGraphicsPixmapItem {
public:
  MyGraphicsItem(): QGraphicsPixmapItem() {}

protected:
  void mousePressEvent(QGraphicsSceneMouseEvent* event) {
    // do stuff. Will be called when clicked exactly on the image
    QGraphicsPixmapItem::mousePressEvent(event);
  }
}

Solution

  • Thanks to SteakOverflow for a point in the right direction.

    Aiiright, here's what you gotta do:

    class MyGraphicsItem: public QGraphicsPixmapItem {
    public:
      MyGraphicsItem(): QGraphicsPixmapItem() {
        // Change shape mode in constructor
        setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
      }
    
    protected:
      void mousePressEvent(QGraphicsSceneMouseEvent* event) {
        // do stuff. Will be called when clicked exactly on the image
        QGraphicsPixmapItem::mousePressEvent(event);
      }
    }
    

    Alternatively, you can do:

    class MyGraphicsItem: public QGraphicsPixmapItem {
    public:
      MyGraphicsItem(): QGraphicsPixmapItem() {}
    
    protected:
      void mousePressEvent(QGraphicsSceneMouseEvent* event) {
        // do stuff. Will be called when clicked exactly on the image
        QGraphicsPixmapItem::mousePressEvent(event);
      }
    
      // ::shape defines collision. 
      // This will make it a rect based on general dimensions of the pixmap
      QPainterPath shape() const {
        if(!pixmap().isNull()) {
            QPainterPath path;
            path.addRect(0, 0, pixmap().width(), pixmap().height());
            return path;
        } else {
            return QGraphicsPixmapItem::shape();
        }
      }
    }