MousePressEvent in view and items in Qt
QGraphicsView isn't really a good place to handle scene-specific events. Instead, you'll need to override QGraphicsScene::mousePressEvent. I would recommend something like this:
void CustomScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (itemAt(event) == NULL)
{
// do stuff if not clicked on an item
}
else
{
QGraphicsScene::mousePressEvent(event); // this forwards the event to the item
}
}
Note that QGraphicsScene::itemAt might give you difficulties if you have items with the ItemIgnoresTransformations flag set to true. Look to the docs for QGraphicsScene::itemAt for how to resolve this.
fibera
Updated on June 09, 2022Comments
-
fibera almost 2 years
I have a custom QGraphicsView and a custom QGraphicsItem. I want the Item to handle my click if I click in the item, else I want the click to be handled by the View.
But when I click on the item, the item handles the click. This is ok. But if I click somewhere else the click isn't handled at all. All the code in my classes that have anything to do with mouseEvents is below.
class CustomView : public QGraphicsView { Q_OBJECT public: void mousePressEvent(QGraphicsSceneMouseEvent *event); }; void CustomView::mousePressEvent(QGraphicsSceneMouseEvent *event){ cout << "pressing in view"; } class CustomItem : public QGraphicsItem { public: CustomItem(CustomView* widget) void mousePressEvent(QGraphicsSceneMouseEvent *event); }; CustomItem::CustomItem(CustomView* widget){ setFlag(ItemIsSelectable); setFlag(ItemIsMovable); } void CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event){ cout << "pressing in item"; }
It seems that when I remove the mousePressEvent function from the CustomItem class and change in the CustomView the mousePressEvent function to:
void CustomView::mousePressEvent(QMouseEvent *event){ cout << "pressing in view"; }
the CustomView handles all the mouseEvents.
How can I let the CustomItem handles the clicks in the items and the CustomView handle all the other clicks?
Thank you.
EDIT
So now I have changed it to:
class CustomView : public QGraphicsView { Q_OBJECT public: }; class CustomScene : public QGraphicsScene { protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); }; void CustomScene::mousePressEvent(QGraphicsSceneMouseEvent *event){ cout << "pressing in scene"; } class CustomItem : public QGraphicsItem { public: CustomItem(CustomView* widget) protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); }; CustomItem::CustomItem(CustomView* widget){ setFlag(ItemIsSelectable); setFlag(ItemIsMovable); } void CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event){ cout << "pressing in item"; }
A Click in the scene but not in an item get handled by the scene. But clicks in the items dont get handled by the items itself, instead it get handled by the scene. Unless if you click 2 times really fast on the items it gets handled by the scene and the item.
Any ideas?
-
Kunal about 12 yearstry overriding
QGraphicsScene::mousePressEvent ( QGraphicsSceneMouseEvent * mouseEvent )
method in QGraphicsScene, instead of QGraphicsView -
Anthony about 12 yearsI think your "CustomWidget::mousePressEvent" is supposed to be "CustomView::mousePressEvent" (or vice versa).
-
fibera about 12 years@Kunal Ty for your input, I moved the mousePressEvent to the scene but I still have a problem with it
-
fibera about 12 years@Anthony Yes indeed, I changed it in the code. Ty for noticing.
-
-
fibera about 12 yearsOk, so I removed the QGraphicsView::mousePressEvent(QGraphicsSceneMouseEvent) and added that function to the custom QGraphicsScene. Now if I click somewhere not on an item the scene handles my click. If I click on an item the scene also handles my click. But if I click 2 times very fast on the item, the item and the scene handle my click.
-
Anthony about 12 years@fibera I realized a mistake I made in my answer. Try out the edited answer and let me know how it goes.
-
Anthony about 12 years@fibera No problem. I just remembered that QGraphicsView also has an itemAt method, so if you wanted, you could ditch the custom QGraphicsScene in favor of your custom QGraphicsView as you were originally trying. However, I still feel that scene-specific events should be handled by QGraphicsScene... it's up to you!