PDA

View Full Version : mouse click in QGprahicsScene



Morea
17th November 2006, 16:50
I'm a little puzzled by how the mouse works in the QGraphicsScene.
If I first click on an item in the view, and then click on a empty space where the item should be placed, how do Iwrite this in code?

It seems right now, that if no item is selected, nothing happens, the event is ignored. Is this true?
I'm a little confused with what to write in the

mousePressEvent(QGraphicsSceneMouseEvent*) function. for the class that is derived from the QGraphicsScene.

aamer4yu
18th November 2006, 05:12
you cuould use QGraphicsScene::items() functions to get the list of items when mouse is pressed...
then u cud place the first item on next mouse click by using the setPos() function

hope this helps :)

Morea
23rd November 2006, 23:30
Here is an update of the question about clicking in the view and getting stuff to happen.

If I have

class Map:public QGraphicsScene {...};
class Town: public QGraphicsPixmapItem {...};
class Army: public QGraphicsPixmapItem {...};

and the GraphicsView contains a large Map object (a huge pixmap) that fills the entire view. Then there are Townand Army objects on the map.
Now I want to be able to click on the Map obj and have code that does one thing if a Army is clicked, or a Town is clicked, and does something else if only the Map object is clicked.

Perhaps the Town should only react to the the Leftbutton.

How should I implement this with the mousePressedEvent ? I have added mousePressEvent to the classes, but I'm not sure if it is done correctly. It seems that it reacts differently. Sometimes it reacts as if there were no Army, evern if I click on an army.
Any good advice from the Qt Gurus that knows how this should be done, would be very nice.

aamer4yu
24th November 2006, 04:26
Well...
I too have done something similar though my problem was little different. U can refer it to thread http://www.qtcentre.org/forum/f-qt-programming-2/t-how-to-drop-items-in-a-dock-widget--4505.html

I eventually implemented cut-paste from one scene to another. The following may help you.

Install a filter on the view or the main window. Psuedo code for the mousPressEvent is ..



mousPressEvent()
{
QGraphicsItem *item = itemAt(event->pos()); // make sure pos is in proper scene cordinates
cast_pointer of item;
check pointer type
if (pointer == Town)
{ // code for town
}
else if(pointer == Army)
{ //code for army
}
else if(pointer==map)
{
}
}

Morea
24th November 2006, 07:41
Would it be possible to reimplement the mousePressEvent() for the GraphicsScene instead of the GraphicsView?

The most important thing is though that you only suggest mousePressEvent for one class. Not more than one as I have it right now. I'll try that. Thanks.

Bitto
7th December 2006, 18:51
The correct way to do this is to first call the scene's event handler, and then check if the mouse event was accepted or ignored by the scene.

Reimplement mousePressEvent in QGraphicsScene like this:



void CustomScene::mousePressEvent(QGraphicsSceneMouseEv ent *event)
{
// First check if any items on the scene accept the event
QGraphicsScene::mousePressEvent(event);

if (!event->isAccepted()) {
// Someone clicked outside an item, or on an item that doesn't
// accept mouse events.
}
}


This is better than checking if there are items at the mouse position with QGraphicsScene::items(), because certain items are transparent for mouse events. Like landscape items, in a game scene.

aamer4yu
8th December 2006, 04:14
What about View ? if we handle the mouse press event in view rather than scene , which one is better ??

Hope i am making sense :D

Bitto
12th December 2006, 09:30
Sure, you can do the same thing in the view, but it's better to handle events for the scene. The view's responsibility is to visualize and navigate the scene. If you handle events in the scene, you can use standard views and still get the correct mouse behavior.

aamer4yu
13th December 2006, 03:58
Ok fine..
but how do I check if the Drag event originated from the scene ? I had implemented things in scene itself, but got stuck when I had to check if it originated from the scene.
Because in Scene event, the source() is widget which u have to set at the time of Drag.

:(

Bitto
20th December 2006, 20:56
Well all Graphics Scene events come with a widget, and the widget is the originator of the event. So if you want to know what widget started the drag, just pull it out from, for example, the QGraphicsSceneMouseEvent that starts the drag.



void MyItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
// event->widget() is the originating widget, and also the viewport
// of the originating QGraphicsView. So event->widget()-parentWidget()
// gives you the view.
}

aamer4yu
21st December 2006, 05:03
Actually I wanted to check if the Drag started from this scene or not..

in

MyScene::mousePressEvent(..)
{
// Start drag
}


MyScene::dropEvent(QGraphicsSceneDragDropEvent * event )
{
// How to check if this event started from this scene or some other scene..
// how can I compare if(this == event->widget()) ??

}

Also i guess if i am starting the drag in scene, I have to handle all the move events and setting of position of item in the scene.. right ??

Bitto
21st December 2006, 08:21
You know the view, so you can easily ask for the scene:



QWidget *viewport = event->widget();
QGraphicsView *view = viewport ? qobject_cast<QGraphicsView *>(viewport->parentWidget()) : 0;

QGraphicsScene *scene = view->scene();