[solved]QGraphicsObject mousePressEvent
-
Hi Qt guys!
I have a problem with the mouse press event and I think, I forgot something.
In earlier projects, it worked well, but now, I got a confused problem:I have a GraphicsView with GraphicsObject in it:
@View::View(QWidget *parent) : QGraphicsView(parent)
{scene = new QGraphicsScene(); this->setScene(scene); pixmapitem = new QGraphicsPixmapItem(NULL,NULL); scene->addItem(pixmapitem);
}@
The pixmap are filled later with data...
Then, I add self-defined objects in it which has a bounding rect:
@QRectF ThermalPoint::boundingRect() const
{
return QRectF(0, 0, 25, 25);
}@and a mousepressevent:
@void ThermalPoint::mousePressEvent ( QGraphicsSceneMouseEvent * event ) {qDebug() << "EVENT: " << event->pos();
}@
Even if i'm not clicking on the object, i got a mouse press event on it.
Output:
@EVENT: QPointF(293.198, 242.341)
EVENT: QPointF(14.2554, 265.458)
EVENT: QPointF(179.155, 87.4587)@how is that possible? The clicked point are out of range of the object, because it has a size of 25x25 pixel. Why is a mousePressEvent recognized?
-
Have you reimplemented shape() for your item? For hit testing, shape() is used, not the boundingRect. However if you don't define a shape, it is automatically calculated from your boundingRect.
-
Things I would try in your situation
- Make a clean and rebuild, just to be sure this isn't some fluke
- Set a breakpoint in the mousePressEvent, and see where (in Qt) the event is coming from
-
I am cleaning and rebuilding all the time, nothing helps.
That happens after clicking anywhere in the scene (Breakpoint at the beginning of the items mousePressEvent:
@0 ThermalPoint::mousePressEvent th_view_items.cpp 128 0x42748b
1 QGraphicsItem::sceneEvent(QEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff7661e57
2 ?? /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff768c640
3 ?? /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff76a1115
4 QGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff76a132f
5 QGraphicsScene::event(QEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff76a043a
6 QApplicationPrivate::notify_helper(QObject*, QEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff70a28ec
7 QApplication::notify(QObject*, QEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff70a525b
8 QCoreApplication::notifyInternal(QObject*, QEvent*) /usr/lib/x86_64-linux-gnu/libQtCore.so.4 0x7ffff6b7863e
9 QGraphicsView::mousePressEvent(QMouseEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff76b7c31
10 THView::mousePressEvent th_view.cpp 231 0x416402
11 QWidget::event(QEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff70efa70
12 QFrame::event(QEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff74a2486
13 QGraphicsView::viewportEvent(QEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff76ba24b
14 QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) /usr/lib/x86_64-linux-gnu/libQtCore.so.4 0x7ffff6b787a6
15 QApplicationPrivate::notify_helper(QObject*, QEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff70a28bc
16 QApplication::notify(QObject*, QEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff70a5a33
17 QCoreApplication::notifyInternal(QObject*, QEvent*) /usr/lib/x86_64-linux-gnu/libQtCore.so.4 0x7ffff6b7863e
18 QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff70a8933
19 ?? /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff711de54
20 QApplication::x11ProcessEvent(_XEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff711ce81
... <Mehr> @ -
Take a look at the code at this call stack entry:
@4 QGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent*) /usr/lib/x86_64-linux-gnu/libQtGui.so.4 0x7ffff76a132f @Scroll up from the instruction pointer. You should see a foreach loop looking something like this:
@foreach (QGraphicsItem *item, cachedItemsUnderMouse)@- Is your item contained in "cachedItemsUnderMouse"?
If so, find out why. The code to determine cachedItemsUnderMouse is a bit further above. It should start with
@if (cachedItemsUnderMouse.isEmpty())@- Do you get into the If just prior to your mouse click? If so, you can step into the 'itemsAtPosition' call and find out why your item is (incorrectly) returned.
-
okay, over the debugger, I can't go to the code referred to the function, because I can only see the assembler code and that doesn't help me anyway.
I downloaded the Qt source code to get more information
My object have to be in the cachedItemsUnderMouse list, otherwise (as I see), a mousePressEvent would never be called.
I tried to find out, which function is responsible for putting my item in the list
I stacked at this function:
@QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode,
Qt::SortOrder order, const QTransform &deviceTransform) const
{
Q_D(const QGraphicsScene);
return d->index->items(rect, mode, order, deviceTransform);
}
@I cannot do more.
I have now reduced my code in the item part to the minimum and nothing changed.
I will now find out, if I can configure anything in the scene rect. If I found a reason for that, I will post it.
Thanks for your help
-
Two more things to try:
- Make sure your entire item is filled by painting a background over the whole of the boundingRect. You can set the flag QGraphicsItem::ItemClipsToShape and paint a huge rectangle in the background. That way, you would see if something strange happened to your item's shape.
- Check the deviceTransform. Are you using some kind of zoom, for example?
-
I have filled my item with a huge background (500x500), but it has only a size of 25x25 (as my boundingRect() ). So that shall work.
I have also but that output in my code:
@ qDebug() << "ContainsItemBoundingRect" << scene->items(mapToScene(event->x(),event->y()), Qt::ContainsItemBoundingRect, Qt::DescendingOrder).count();
qDebug() << "ContainsItemShape" << scene->items(mapToScene(event->x(),event->y()), Qt::ContainsItemShape, Qt::DescendingOrder).count();
qDebug() << "IntersectsItemShape" << scene->items(mapToScene(event->x(),event->y()), Qt::IntersectsItemShape, Qt::DescendingOrder).count();
qDebug() << "IntersectsItemBoundingRect" << scene->items(mapToScene(event->x(),event->y()), Qt::IntersectsItemBoundingRect, Qt::DescendingOrder).count();@everytime, it is 1 (my background item, which is only a QGraphicsPixmapItem). When I click on a ThermalPoint item, it is 2, so that seems also to work.
I did some scaling, but also after deactivating it completely, it doesn't help.
I am now thinking about to make an own mousePressEvent with the scene->items function, which recognize the clicked item. It makes no sence, why it's not working.
-
I would try to take an existing sample project, and add your class to that. That way you can find out whether the issue originates somewhere from your QGraphicsObject subclass, or from somewhere else (e.g. from changes to scene or view).
I have worked a lot with GraphicsView, and don't remember such behavior, so I am still hesitating to suggest a bug in Qt (but it is possible, of course).
-
okay, I solved the problem.
Thank you, Asperamanca for your great help!So, the problem was, that I have implemented mousePressEvent, mouseMoveEvent and mouseReleaseEvent.
I forgot to put QGraphicsView::mouseReleaseEvent(event); in the release event. What happend ?
When I add an object, it gets automatically clicked but never get out of the list (the cachedItemsUnderMouse list, you mentioned before). So, the item is always in the list and so on, it is always "clicked". I think, that is the reason, why it "never" worked. Now I can continue my work :)