PDA

View Full Version : clear()..in a QGraphicsScene..



salmanmanekia
13th June 2010, 09:49
Hi all
I am using a clear() method in one of the clases inherited from QGraphicsScene ,it compiles succesfully and runs once quite succefully but when i give the inputs again and want a redraw by using clear function the application hangs ..below is the excerpt of the code..


QWIDGET CLASS
void InputItems::gridParam()
{
qDebug() << "Grid Parameter ";
bool ok;
myView->setParam(heightValue->text().toDouble(&ok), widthValue->text().toDouble(&ok));
}


VIEW CLASS
void View::setParam(double heightValue,double widthValue)
{
myScene->drawScene(heightValue,widthValue);
qDebug() << "View Height ";

}


SCENE CLASS
..
QVector <QGraphicsRectItem*> rectItem;
..
void Scene::drawScene(double heightValue, double widthValue)
{
this->heightValue = heightValue;
this->widthValue = widthValue;
clear();
drawMatrix(); //uses and draws a rect items
qDebug() << "Scene Height " << heightValue ;
}

tbscope
13th June 2010, 10:57
Be careful.
The documentation says this when using clear()

Removes and deletes all items from the scene
Note that clear() also deletes your items on the scene.

I guess you do not create a new rectItem again when updaing the scene. Thus, you try to access an inexisting item which leads to a crash.

salmanmanekia
13th June 2010, 11:10
absolutelyt right...i understand that...thanks...
now i am creating my item in the drawMatrix function instead of declaring it as a class variable....but then it wont be visible anymore out of the function ,what else can i do here..??

wysota
13th June 2010, 12:48
What does drawMatrix() look like?

salmanmanekia
13th June 2010, 12:58
void Scene::drawMatrix()
{
QVector <QGraphicsRectItem*> rectItem; // i want this to be as a global variable /class variable so it is visible everywhere in the class...

qDebug() << "Scene Matrix ";

qreal rectWidth = (300 / widthValue) - 5;

qreal rectHeight = (300 / heightValue) - 5;

qreal startX = 1;

qreal startY = 1;


int counterX = 0;

int counterY = 0;

int number = 0;

for(counterY = 0; counterY < heightValue; ++counterY) {

startY = counterY * (rectHeight + 5);

for(counterX = 0; counterX < widthValue; ++counterX) {

startX = counterX * (rectWidth + 5);

rectItem << addRect(0,0,rectWidth,rectHeight,QPen(),Qt::NoBrus h);

qDebug() << counterX << counterY ;

rectItem.at(number)->setPos(startX,startY);

++number;

}

}

too add to this piece of code ,i tried using QVector <QGraphicsRectItem *> *rectItem instead of QVector <QGraphicsRectItem*> rectItem ...so that i can declare it new after every clear() statement ,but it wont help ,even i am not sure that is this appropiate logically but i just tried to tried...:)

wysota
13th June 2010, 13:10
You don't have to delete and recreate all the items each time you change the matrix. The problem you have is probably caused by the line #34. When you clear the scene, items are deleted but they are not removed from your global vector. It's enough that you clear the vector as well and your code should work. I would change the #34 line to use the result of addRect() instead of getting the item from the vector each time. In other words your code can be simplified and clarified and I think you should focus on that.

salmanmanekia
13th June 2010, 13:29
You don't have to delete and recreate all the items each time you change the matrix.
Why not ?.....what difference does it makes if i use scene.clear() ...or maybe clear the vector...

when you clear the scene, items are deleted but they are not removed from your global vector. It's enough that you clear the vector as well and your code should work
do you mean i shouldnt use scene.clear and just clear the vector and at next user input the new matrix will be redrawn..?
since u r master ..;) i will ask u one more thing ,is it logically correct ,as ahead i have to see if there are any mouse button pushes over a particular rectangle and then do some stuff for it...i mean thats the reason i am using a vector so i can follow each of the rectArea...:o

wysota
13th June 2010, 14:04
Why not ?
Because recreating the same elements over and over again doesn't make sense and it takes time.


.....what difference does it makes if i use scene.clear() ...or maybe clear the vector...
It makes great difference. Clearing the scene deletes items kept in the scene. Clearing the vector doesn't. That's why you need both if you want to have your vector.



is it logically correct ,as ahead i have to see if there are any mouse button pushes over a particular rectangle and then do some stuff for it...i mean thats the reason i am using a vector so i can follow each of the rectArea...:o
I don't understand your question.

salmanmanekia
13th June 2010, 14:16
I don't understand your question.
he question is
"i have decided to use QVector of QGraphicsRectItem because i have to make arbitrary numbers of rectangle and want to see when a user pushes a mouse button on any of the specifice button ,so i can check when and if a mouse event is trigred on a specific rectangle"does this makes it any clear...:)

It makes great difference. Clearing the scene deletes items kept in the scene. Clearing the vector doesn't. That's why you need both if you want to have your vector.

You don't have to delete and recreate all the items each time you change the matrix
The above two lines confuses me should i delete the items and the vector both :confused:
and last but not the least

I would change the #34 line to use the result of addRect() instead of getting the item from the vector each time.
how would you do that and by doing it will my main problem of having the the declaration of QVector<QGraphicsRectItem *> will be outside the member function

wysota
13th June 2010, 14:31
he question is
"i have decided to use QVector of QGraphicsRectItem because i have to make arbitrary numbers of rectangle and want to see when a user pushes a mouse button on any of the specifice button ,so i can check when and if a mouse event is trigred on a specific rectangle"does this makes it any clear...:)
I still don't understand :) You want to know which rect item the mouse was pressed on or...what buttons are you talking about? :confused:



The above two lines confuses me should i delete the items and the vector both :confused:
Clearing the vector doesn't delete the items. So if you have N items, clear the scene, then add (N) items to the vector again without clearing it first will cause your vector to have 2*N items with first N of them being invalid so when you use QVector::at() to access item at position < N then you are accessing an invalid item causing your program to crash. For a local vector it works, because at each time you create a new vector but for a global vector the situation is as I described it.


how would you do that and by doing it will my main problem of having the the declaration of QVector<QGraphicsRectItem *> will be outside the member function
addRect() returns a pointer to the item which you are immediately adding to the vector without storing it anywhere. Then you reach into the vector to get the pointer back and set the position of the item. Instead you can assign the pointer to a local variable first and only then add the item to the vector so that you don't have to immediately query it back causing a segfault as I described earlier.

salmanmanekia
13th June 2010, 18:05
addRect() returns a pointer to the item which you are immediately adding to the vector without storing it anywhere. Then you reach into the vector to get the pointer back and set the position of the item. Instead you can assign the pointer to a local variable first and only then add the item to the vector so that you don't have to immediately query it back causing a segfault as I described earlier.
Does that means that in this way the clear wont delete the items from the scene which are stored in QVector and only the locally declared pointer of QGraphicsRectItem will be cleaned..Right ..??..



I still don't understand You want to know which rect item the mouse was pressed
Right ,that what i am doing all this hardwork for,.....;)

wysota
13th June 2010, 20:07
Does that means that in this way the clear wont delete the items from the scene which are stored in QVector and only the locally declared pointer of QGraphicsRectItem will be cleaned..Right ..??..

No. I'm sorry, I won't give you a lecture here on how pointers work.


Right ,that what i am doing all this hardwork for,.....;)
Subclass the rect item class and reimplement its events. Then you will know which item was clicked. Alternatively just query the scene about the item that is in the position where the event happened with QGraphicsScene::items().

salmanmanekia
13th June 2010, 20:31
No. I'm sorry.
Thats Ok ,i have an old enmity against pointers :p...Still this wont stop me asking a question ,:D

As per your advice i changed the code and it works perfectly and the change is as follow


localRectItem = addRect(0,0,rectWidth,rectHeight,QPen(),Qt::NoBrus h);
localRectItem->setPos(startX,startY);
rectItem.append(localRectItem);

while the previous not-so-good code was


rectItem << addRect(0,0,rectWidth,rectHeight,QPen(),Qt::NoBrus h);
rectItem.at(number)->setPos(startX,startY);

What makes these two pieces of code so different that if i use the second code then i cant declare rectItem as a class variable ...i cant absorb this fact...

I won't give you a lecture here on how pointers work
May be one line answer for that or few line detailed answer is good too..No lectures please.!..:rolleyes:..