PDA

View Full Version : move GraphicsItems within a GraphicsScene



rambo83
3rd November 2009, 18:54
Hello,

I have got the following task, which I cannot achieve since a couple of days:

I have inserten several circles (GraphicsItems) into my scene and after that I would like to change their positions within this scene by dragging them (left mouse button + moving the mouse). I have read almost all information about Drag & Drop, but I still cannot get my items moved through the scene. I have implemented my own class inherited from QGraphicsItem and overriden the functions MousePressEvent() MouseMoveEvent() and MouseReleaseEvent() for this class and after that I also implemented my QGraphicsScene class because I wanted to override the functions DropEvent() and DragEnterEvent(). Actually, I guess that there must be an easier solution without Drag & Drop because the Item is already on the scene, so it is not necessary to drop it there again, right?

The thing I want to do is the following: I create a vector of some points (x and y coordinates) and write the vector elements into the position of generated QGraphicsItems by ( ->setPos() ). During the execution the user should be able to move this items on the scene and thus change the x and y values within the vector elements and the items should remain on the position, where mouse dragging was released, of course.
Help me please to realize this aim.

Thank you

best regards,

Vitali

wysota
3rd November 2009, 19:39
You are confusing two approaches here. Drag&drop is one thing and moving items with a mouse is another thing. If you want your items to be movable, all you need to do is to call this on your item:

item->setFlag(QGraphicsItem::ItemIsMovable);

You don't need to reimplement any events or anything.

rambo83
3rd November 2009, 20:12
Thank you for reply.

this flag is set in the constructor of my QGraphicsItem ( setFlag(ItemIsMovable, true) ) and if I dont override all the functions, I have mentioned, then my item can be moved and it remains on the place where I release my mouse button, BUT I also want to get the new position of the moved item in order to update my vector with the x and y coordinates of points. How can I do that then?

best regards,

Vitali

wysota
3rd November 2009, 21:09
Make sure that you call the base class implementations of those methods from your reimplementations.

But actually you should handle this situation in a different way. Instead of reimplementing mouse operations, reimplement QGraphicsItem::itemChange() and update your data from within there. This way you make sure the data will get updated regardless of the way the item is moved on the scene.

rambo83
4th November 2009, 08:32
Thank you for the advice.
Now I use the itemChange() function and it seems to work, but now I think how to detect index of the moved GraphicsItem and the index of the scene, so that I can update the coordinates within my point vectors.
I have got a
QVector<QGraphicsScene *> vec_scenes;, where I pushed back several scenes. Every scene corresponds to a construct(individual) consisting of two vectors (one for x and another for y coordinates). With this I can then add a certain amount of points (graphicsitems) into the scene for every construct. I have got more than one construct (individuals) within a vector of individuals, so it is like a population. Don't be surprised, I'm working on evolutionary algorithms and want to visualize the process by means of Qt.

So, how can I update the x, y coordinates of an individual , if a graphicsitem within a scene will be moved? Any ideas?

best regards

jano_alex_es
4th November 2009, 08:43
Now I use the itemChange() function and it seems to work, but now I think how to detect index of the moved GraphicsItem and the index of the scene

You can have a QHash (index, pointer) of scenes and search them by id.

So, if you move a QGraphicsItem it's event itemChange(GraphicsItemChange change, const QVariant &value), is called (change == ItemPositionHasChanged). So you can get it's id, and send it whereever you want. You can keep the ID of the scene on each qgraphics item or, better, a pointer.

rambo83
4th November 2009, 11:16
I found out how to find the index of a point within a scene, namely with the following code:

QList<QGraphicsItem *> lst = this->scene()->items();
QList<QGraphicsItem *>::iterator it = lst.begin();
unsigned i=0;
while (it != lst.end()) {
if((*it) == this){
//(*it)->hide();
qDebug() << "index: " << i;
}
++it;
++i;
}
and it works, but then I tried to determine the index of the corresponding scene and it does not work. I think it has something to do with the access to a QVector of another class:

QVector<QGraphicsScene *> scenesPhen = main.getScenes();
QVector<QGraphicsScene *>::iterator it2 = scenesPhen.begin();
qDebug() << "scenesPhen.size() = " << scenesPhen.size();
unsigned j=0;
while (it2 != scenesPhen.end()) {
cout << "(*it2): " << (*it2) << "\t\t scene(): "<< scene()<< endl;
if((*it2) == scene()){
qDebug() << "index of scene: " << j;
}
++it2;
++j;
}
hereby is "main" another class, declared in header file and "getScenes()" is the public function of another class, which gives by the QVector<QGraphicsScene*>.

The cout output gives everytime another combination of addresses, if I move items on different scenes, but actually the addresses of scenes within the scene-vector should remain the same, right? So I guess, that here is somewhere my mistake. But where? Please help...
Thank you

rambo83
4th November 2009, 14:40
my last post is solved... My fault was just to use
mainFrame main; in the header file and then to use it within the cpp file, but then it has nothing to do with the existing mainFrame class, thus all addresses were wrong.
Now I give by the pointer to the mainFrame class in the constructor of Vertex class, so that it has the right pointer at running time.

regards,

Vitali