3

I have a QGraphicsView with a bigger QGraphicsScene that can be dragged. In the QGraphicsScene I have a subclassed QGraphicsItem (TestItem) that displays a QGraphicsPixmapItem, which can have random shapes. (I don't use QGraphicsPixmapItem directly because of extra functionality to be implemented in the future)

I want this item to be movable, but only if the user presses within the shape of the item. If outside the shape, but still inside the boundingRectangle, I want the scene behind it to be dragged. This because the boundingRectangle can be much bigger than the shape and the user doesn't see it, so it would be weird trying to drag the scene near the Pixmap and it not working.

This is my subclassed item:

TestItem::TestItem(QPointF position, QPixmap testImage, double width, 
                    double length, QGraphicsItem * parent):
    QGraphicsItem(parent),
    m_boundingRect(QRectF(0,0,5, 5)),
    m_dragValid(false),
    m_path(QPainterPath()),
    mp_image(new QGraphicsPixmapItem(this))
{
    setBoundingRect(QRectF(0,0,width,length));
    setPos(position - boundingRect().center());
    setFlag(QGraphicsItem::ItemIsMovable);
    mp_image->setPixmap(testImage.scaled(width, length));
    m_path = mp_image->shape();
}

QPainterPath TestItem::shape()
{
    return m_path;
} 

QRectF TestItem::boundingRect() const
{
    return m_boundingRect;
}

void TestItem::setBoundingRect(QRectF newRect)
{
    prepareGeometryChange();
    m_boundingRect = newRect;
}

I've tried overriding the mouse events like this, but all it brings me is no functionality at all when outside the shape but inside the bounding rectangle

void TestItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    if(shape().contains(event->pos()))
    { 
        QGraphicsItem::mousePressEvent(event);
        m_dragValid = true;
    }
}

void TestItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    if(m_dragValid)
        QGraphicsItem::mouseMoveEvent(event);
} 

void TestItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    if(m_dragValid)
        QGraphicsItem::mouseReleaseEvent(event);

    m_dragValid = false;
}

which of course makes sense, but I wouldn't know how to implement the dragging of the scene, since it's the scene itself that sends the mouse events to the graphics item.

(My QGraphicsView is setup to DragMode QGraphicsView::ScrollHandDrag)

Anyone have ideas?

Alexander Stepaniuk
  • 6,217
  • 4
  • 31
  • 48
tripleM
  • 131
  • 1
  • 10
  • 1
    See related discussion: http://stackoverflow.com/questions/4753681/how-to-pan-images-in-qgraphicsview – Archie Jan 20 '15 at 16:24
  • Yes, thank you @Archie. That discussion had exactly what I was looking for. I just needed to add a `event->ignore();` to my mouse events. I'll write a solution – tripleM Jan 21 '15 at 08:39

2 Answers2

5

I figured it out. I only needed to add a event->ignore(); to my mouse events.

void TestItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
   if(shape().contains(event->pos()))
    {  
        QGraphicsItem::mousePressEvent(event);
        m_dragValid = true;
    }
    else
        event->ignore();
}

void TestItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    if(m_dragValid)
         QGraphicsItem::mouseMoveEvent(event);
    else
        event->ignore();
} 

void TestItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    if(m_dragValid)
        QGraphicsItem::mouseReleaseEvent(event);
    else
        event->ignore();

    m_dragValid = false;
}
tripleM
  • 131
  • 1
  • 10
0

You just need to enable QGraphicsItem::ItemClipsToShape flag:

The item clips to its own shape. The item cannot draw or receive mouse, tablet, drag and drop or hover events outside its shape. It is disabled by default.

Pavel Strakhov
  • 39,123
  • 5
  • 88
  • 127
  • I have done this, and nothing changes. I also tried `QGraphicsItem::ItemClipsChildrenToShape` with no success. The item moves if pressed inside the bounding rectangle – tripleM Jan 21 '15 at 08:35