PDA

View Full Version : QGraphicsItem mouse events



zgulser
10th February 2009, 13:45
Hi,

I have some QGraphicsItems on my scene. I'am percepting mouse events in the QGraphicsView class. Once I try to reimplement mouseMoveEvent in one of my QGraphicsItem, it does't do anything.

Any ideas?

Regards.

janus
10th February 2009, 13:54
Hi,

take a look at QGraphicsItem::setAcceptHoverEvents

zgulser
10th February 2009, 13:58
Well, I don't wanna percept hover actually.
I want to percept mouse move or press when the cursor is moved over the item for example.

Regards.

jpn
10th February 2009, 14:13
In order for a graphics item to receive mouse move events, it must first accept the mouse press event.

zgulser
10th February 2009, 14:24
Hi again,

I reimplemented mouseMoveEvent and mousePressEvent in the QGraphicsView class. From QGraphicsView::mousePressEvent(), I can handle which item is pressed by calling ...items(QPointF). But I want to handle it from the QGraphicsItem class. To do this I reimplemented mousePressEvent() again in the QGraphicsItem class but I couldn't get any respond upon any mouse presses although I first reimplemented mousePressEvent.

Regards

jpn
10th February 2009, 14:42
I reimplemented mouseMoveEvent and mousePressEvent in the QGraphicsView class.
Why? QGraphicsView is supposed to forward mouse events to the scene, which in turn delivers them to those items that they belong to. Custom mouse event handlers in the view tend to break the graphics view framework event handling unless you really now what you're doing.


From QGraphicsView::mousePressEvent(), I can handle which item is pressed by calling ...items(QPointF).
The default implementation of QGraphicsScene already does this in an efficient way.


But I want to handle it from the QGraphicsItem class.
The default implementation of QGraphicsScene delivers mouse events to those items that they belong to.


To do this I reimplement mousePressEvent() again in the QGraphicsItem class but I couldn't get any respond upon any mouse presses although I first reipmlement mousePressEvent.
Probably because the QGraphicsView::mousePressEvent() reimplementation breaks the event delivery chain. Make sure you call the base class implementation.

zgulser
10th February 2009, 15:06
Why? QGraphicsView is supposed to forward mouse events to the scene, which in turn delivers them to those items that they belong to. Custom mouse event handlers in the view tend to break the graphics view framework event handling unless you really now what you're doing.

I have a QGraphicsScene object inside my QGraphicsView. So that's why I reimplemented mouse events in QGraphicsView. I did the following

void QGraphicsView::mousePressEvent(QMouseEvent* mouseEvent)
{
QPointF p = mapToScene(mouseEvent.x(), mouseEvent.y());
itemsList = this->scene.items(p);
...
}


The default implementation of QGraphicsScene already does this in an efficient way.

Ok.



The default implementation of QGraphicsScene delivers mouse events to those items that they belong to.

How I am handling events in items? By reimplementing mouse events in QGraphicsItems?



Probably because the QGraphicsView::mousePressEvent() reimplementation breaks the event delivery chain. Make sure you call the base class implementation.

What do you mean by base class implementation?

Thanks.

jpn
10th February 2009, 15:32
I have a QGraphicsScene object inside my QGraphicsView. So that's why I reimplemented mouse events in QGraphicsView. I did the following

void QGraphicsView::mousePressEvent(QMouseEvent* mouseEvent)
{
QPointF p = mapToScene(mouseEvent.x(), mouseEvent.y());
itemsList = this->scene.items(p);
...
}

I don't understand what you mean. What are you trying to achieve with that implementation?


How I am handling events in items? By reimplementing mouse events in QGraphicsItems?
Yes.


What do you mean by base class implementation?
I meant something like this:


void SubClass::function()
{
BaseClass::function(); // <-- call the base class implementation
// ... do your own things
}

But looking at your current implementation, I'm not convinced at all you should even need to reimplement QGraphicsView::mousePressEvent().

zgulser
10th February 2009, 15:42
Thanks JPN for your usefull answers.

What I did is something different. Instead of reimplementing mouse events inside QGraphicsScene, I reimplemented those in QGraphicsView and then used mapToScene in order to achieve convenience. By doing so, I figured out that mouse events are also delivered to the corresponding items.

By the way, I just missed to write QGraphicsView::mousePressEvent() inside the QGraphicsView::mousePressEvent() { ... }. That's why it didn't work until now.

King Regards

jpn
10th February 2009, 15:50
What I did is something different. Instead of reimplementing mouse events inside QGraphicsScene, I reimplemented those in QGraphicsView and then used mapToScene in order to achieve convenience.
But you still haven't given a valid point why are you doing all this in the first place. What's wrong with the default event handling? Maybe there's a better way to do whatever you're trying to do... :)

zgulser
10th February 2009, 21:20
But you still haven't given a valid point why are you doing all this in the first place. What's wrong with the default event handling? Maybe there's a better way to do whatever you're trying to do... :)


First of all

I wonder what exactly does the statement in the following mean? This is from the documentation.

"QGraphicsScene's event propagation architecture schedules scene events for delivery to items, and also manages propagation between items. If the scene receives a mouse press event at a certain position, the scene passes the event on to whichever item is at that position."

Does it mean that I should handle mouse events first in QGraphicsScene and then in QGraphicsItem class?


Secondly,

I guess you mean QGraphicsView by first place. If it is, here is my reason;

I have a view which has a QGraphicsScene object in it. So I do not create any class from QGraphicsScene. If I created, be sure that I did the way you told above as normally which might be a better way. I'am totally open for such development issues with no argue:)

By the way, what's wrong with handling mouse events in the QGraphicsView?
Regards.

jpn
10th February 2009, 21:38
It means that QGraphicsScene delivers events to QGraphicsItems in an intelligent way. If the top most item does not handle the event, it gets propagated to the item underneath and so on. You should not break the fine mechanism by reinventing the wheel... ;)

What do you actually mean with "having a view which has QGraphicsScene object in it, but not creating any class from QGraphicsScene"?

zgulser
10th February 2009, 23:21
It means that QGraphicsScene delivers events to QGraphicsItems in an intelligent way. If the top most item does not handle the event, it gets propagated to the item underneath and so on. You should not break the fine mechanism by reinventing the wheel... ;)

:) No man, I just try to find out the correct way to do this. I actually did what the documentation say;

"All mouse events and drag and drop events are originally received as view coordinates, and you need to map these coordinates to the scene in order to interact with items."

But anayway, please answer how to handle mouse events?? Ok it is done by QGraphicsScene in an intelligent way:). I got it but how? I mean how an item percept mouse move when the cursor is on that item? Does the item percepts those mouse events implicitly by QGraphicsItem::mousePressEvent, QGraphicsItem::mouseMoveEvent etc. ?


What do you actually mean with "having a view which has QGraphicsScene object in it, but not creating any class from QGraphicsScene"?

It means I have a class which is also QGraphicsView and in this class I have a variable QGraphicsScene.( simple aggregation ).

jpn
11th February 2009, 12:19
:) No man, I just try to find out the correct way to do this. I actually did what the documentation say;

"All mouse events and drag and drop events are originally received as view coordinates, and you need to map these coordinates to the scene in order to interact with items."
You reimplement QGraphicsView mouse event handlers only if you need to do something custom. I don't see you doing anything that would require reimplementing those.


I mean how an item percept mouse move when the cursor is on that item?
They are called hover events if you're not pressing anything. Graphics items do not receive hover events by default because of performance reasons. But they can be turned on as already suggested by janus in the beginning of this thread.


Does the item percepts those mouse events implicitly by QGraphicsItem::mousePressEvent, QGraphicsItem::mouseMoveEvent etc. ?
Yes. The top most item will receive the events first, and if it doesn't handle them, the events will get propagated to the second top most item and so on.


It means I have a class which is also QGraphicsView and in this class I have a variable QGraphicsScene.( simple aggregation ).
I don't understand what's the relation to this problem. So you have a graphics view and a scene. Fine, that's just like anyone who uses the graphics view framework. :) As I already mentioned, you don't need to inherit QGraphicsView nor QGraphicsScene in order to be able to receive mouse events in graphics items. It is already handled by the framework.