PDA

View Full Version : Mouse grabbing - Question for experts



jfmartel
20th October 2011, 08:24
Hi you all Qt experts of the world.

I have some experience in Qt yet but all is self instructed. So far I always succeeded to find all I needed in the very extensive Qt library and I am very happy. But now for the first time I am caught in a small hitch that I thought some more experienced programmers could help me with.
I Use Qt embedded under linux on an ARM with a touch screen.

Situation:
I want to create a scroll list that is scrollable with the finger, like the songs list of an Iphone or Ipod touch. I use Graphics View framework.
Each entry of my list is a custom object derived from QGraphicsItem. So far so good. I already implemented everything with a button to scroll up and down and it works fine. Now I want to change it for finger scrolling. If you click on an item of the list it sends a message to play a song.

What I did:
I created my own QGraphicsWidget derived widget that is invisible but covers the scrollable area of the screen, it's called CMouseScrollerWidget. This widget was programmed to catch mouse events, manage the scrolling and forward the position of the mouse (in scroll mode) to the parent item so it can then scroll the list. That works.

What is the problem:
My problem appears when the user only click-and-release an item of the list to select it (to start a song for instance). What happens is that the CMouseScrollerWidget grabs the mouse because it's got no other choice. If the user releases without moving the mouse there is no way for the list item widget to receive the MouseReleasedEvent because the mouse is grabbed by CMouseScrollerWidget. I tried a lot of things and even if I call ignore() there is no way of propagating the MouseReleaseEvent to the other widget under the mouse.

Now:
I know that I could implement a signal that would be monitored by all the items in the list and notify them when the mouse is only clicked. Then each item shall check if the mouse pointer is pointing on themselves and this is not very efficient.
I could also notify the parent which could call QGraphicsScene::items(QPoint) and parse the list to find the good item and notify it. Again, I think this is not very efficient because I would have to implement an identification mechanism for my graphics items so that the parent is shure it is pointing to the list item and not the background image widget...
Another solution that I thought of would be for the parent to parse the list of list items widget and find the item that is at the click point... again not very efficient since Qt does this very well (and kind of already did when the user clicked the mouse)

What I'm looking for:
Is there a way of using the very efficient object-finding feature of Qt. My best bet would be to be able to ignore() the MouseReleaseEvent so it is directly propagated to the exact good item. That is what I think would be the most efficient scheme but mouse grabbing mechanism is not permitting this behavior.
If it's not possible, is there some other kind of way to notify visible objects under the mouse only ?

Thank you all, it was a long question but I thought giving more details would help having a precise answer !
J-F

fullmetalcoder
20th October 2011, 09:01
Is there anything preventing you from handling mouse events directly in the graphics view without messing with mouse grabbing?

nish
20th October 2011, 09:59
do not overlay a widget. Its overkill. Use an eventFilter

Spitfire
20th October 2011, 10:20
QGraphicsView can manage the mouse event so you don't need transparent overlay to do it.

What I would do is to make the items to register touch start/move/end and qgraphicsview to register touch move only.
now when user touches the screen item registeres the touch and if next action is release - then the song is played (signal emited etc).
if instead of release, next action is move, item registers it and shouldn't play the song on release (simple bool set to true on touch and to false on move will do, check the bool on release to know what to do).
this way touch-release will play a song, but touch-move-release will not.
last step is to implement scrolling in qgraphics view move event handler and you're good to go.

I hope that's not too vague and gives you my general idea (to mimic ios touch/scroll). I did something like that in js and it worked well.

jfmartel
21st October 2011, 08:18
Is there anything preventing you from handling mouse events directly in the graphics view without messing with mouse grabbing?

Maybe I failed to make this clear but this question was part of my (bigger) question. If there was a way for widgets in a view to get all mouse click-move-release events without having to grab the mouse (as soon as you accept() an event you grab the mouse) then my problem would be fixed.

Added after 6 minutes:


QGraphicsView can manage the mouse event so you don't need transparent overlay to do it.

What I would do is to make the items to register touch start/move/end and qgraphicsview to register touch move only.
now when user touches the screen item registeres the touch and if next action is release - then the song is played (signal emited etc).
if instead of release, next action is move, item registers it and shouldn't play the song on release (simple bool set to true on touch and to false on move will do, check the bool on release to know what to do).
this way touch-release will play a song, but touch-move-release will not.
last step is to implement scrolling in qgraphics view move event handler and you're good to go.

I hope that's not too vague and gives you my general idea (to mimic ios touch/scroll). I did something like that in js and it worked well.

I see exactly what you want to do and that happens to be what I also want to do. The problem is not if I use an overlay widget or not (I think). My problem is that if I grab the mouse events (accept() the mouse click event) then no other widget will receive the move and release events until the button is released. And in the other way, if a widget don't accept the click event then it will not receive the move and release events... I see now way whatsoever for all the widgets to receive all the events. And that is the core of my problem !

Thanks for your answer :)

fullmetalcoder
21st October 2011, 19:24
If there was a way for widgets in a view to get all mouse click-move-release events without having to grab the mouse (as soon as you accept() an event you grab the mouse) then my problem would be fixed.

Event filter (http://doc.qt.nokia.com/stable/qobject.html#eventFilter)?

jfmartel
22nd October 2011, 08:58
Event filter (http://doc.qt.nokia.com/stable/qobject.html#eventFilter)?


Ok, I'll dig into that.

jfmartel
23rd October 2011, 02:03
Okay,

Thanks all for your answers. With your help, I discovered the use of Event filters today and it will be very usefull in my Qt future :)

Once I understood how filters worked then what you said guys was right. Overlaying widgets was not necessary. I only filtered the usefull events and I get good control over the event propagation. It's a very clever system.

Thanks to all of you who took time to post.