PDA

View Full Version : erratic behavior of graphics items



sajis997
3rd February 2012, 20:47
Hello forum,

Please Check the attached image. 7355. You can see that two elliptical items are connected by an arrow graphics item.

If the user clicks the small ellipse inside the large ellipse an arrow item is instantiated. The arrow item is extended with the mouse move and mouse release event.

I also have over-ridden the following function so that the arrow is adjusted even after the position changes of the elliptical items.



QVariant H3DHierarchyArrowDockGraphicsItem::itemChange(Grap hicsItemChange change, const QVariant &value)
{
switch(change)
{
case ItemPositionHasChanged:
foreach(H3DHierarchyArrowGraphicsItem *arrow, m_hierarchyArrowList)
arrow->adjust();
break;
default:
break;
}

return QGraphicsItem::itemChange(change,value);
}




But at some point i get the following output while moving the items inside the scene.
7356



As you can see the arrow is totally detached from the destination item. And the arrow is attached back while moving the elliptical items - not so pleasant behavior, is it?

To get a functional one i have taken hint from elastic nodes, diagram scene example and voreen editor( Qt based volume rendering editor), but it seems that i have missed some ideas to get it right.

To provide me with useful hint i am also attaching the corresponding source files that you need to look into.

735973587357


If the arrow has both the source and destination item i am doing the intersection test just as in the diagramscene example of Qt so that the destination point always slides on the arc of the ellipse. All the arrows that are created has the small ellipse and another larger ellipse as the destination item.

In inside the adjust() function i am trying to update the destination point of the arrow which seems not to be working. Please make some time to go through it.


Thanks
Sajjad

sajis997
4th February 2012, 13:02
Hello forum,

I have not got any reply yet on this issue. Please let me know if my elaboration of the problem is not clear enough.

If two graphical items of different types are connected to a single arrow at both ends, is mandatory to call the adjust() function of arrow graphics item from the both the graphical items?


I am looking forward to some feed-back



Regards
Sajjad

wysota
4th February 2012, 14:56
It would help if you provided a minimal compilable example reproducing the problem.

sajis997
8th February 2012, 06:35
This post has been merged into this thread!

Hello forum,

With the help of the forum i have made some changes to the diagram scene example where i added elliptical item as follows:



case Ellipse:
{
//declare an ellipse with the bounding rectange
QGraphicsEllipseItem item(-100,-50,200,100);
myPolygon = item.shape().toFillPolygon();
}
break;


I wanted to use the very same idea to implement the intersection test in another project. In my project i have the graphical item has the following definitions for bounding rectange and shape functions:



QRectF RootGraphicsItem::boundingRect() const
{
//!get the bounding rectangle of the enclosing text
QRectF rect = m_textGraphicsItem->boundingRect();


//the following condition decides if the boundary needs
//to be changed
if( rect.width() < m_drawRectMinimumWidth )
rect.setWidth(m_drawRectMinimumWidth);

if(rect.height() < m_drawRectMinimumHeight)
rect.setHeight(m_drawRectMinimumHeight);

//set the rectangle width with the text item spacing
rect.setWidth(rect.width() + getTextItemSpacing() );

//and return the rectangle
return rect;
}

//the following function is for better collission detection
QPainterPath RootGraphicsItem::shape() const
{
QRectF ellipse_rect = boundingRect();

QPainterPath path;

path.addEllipse(ellipse_rect);

return path;
}



But if i try to add the arrow item to my root graphics item using the line intersection example i get erratic behavior - the arrow is not attached to the item and disappears once you move the item inside the scene. You can also recreate the problem in the diagram scene example if you do the following changes




case Ellipse:
{
//declare an ellipse with the bounding rectange
// QGraphicsEllipseItem item(-100,-50,200,100);
QGraphicsEllipseItem item(0,0,200,100);
myPolygon = item.shape().toFillPolygon();
}
break;



You also need to add the following line in the mainwindow.cpp and some additional changes in diagramitem.h:



layout->addWidget(createCellWidget(tr("Ellipse"),DiagramItem::Ellipse),2,0);





enum DiagramType
{
Step,
Conditional,
StartEnd,
Io ,
Ellipse
};



I think i need to adjust some transformational issue here. But i have not found any good reference to it. The manual is not illustrative enough.

Any reference to this issue will be very helpful



Regards
Sajjad

sajis997
8th February 2012, 08:16
Hi

I have managed to recreate the same problem i am having in my project by doing the following changes in the diagramscene example:


Inside the diagramitem.h file i added another item as follows:




enum DiagramType
{
Step,
Conditional,
StartEnd,
Io ,
Ellipse
};




Inside the diagramitem constructor i have added the following:



case Ellipse:
{
//declare an ellipse with the bounding rectange
// QGraphicsEllipseItem item(-100,-50,200,100);
QGraphicsEllipseItem item(0,0,200,100);
myPolygon = item.shape().toFillPolygon();
}
break;



I am sure not how to do this arrow and elliptical intersection test where in my project i have defined the bounding rectangle and shape for the elliptical item as follows:



QRectF RootGraphicsItem::boundingRect() const
{
//!get the bounding rectangle of the enclosing text
QRectF rect = m_textGraphicsItem->boundingRect();


//the following condition decides if the boundary needs
//to be changed
if( rect.width() < m_drawRectMinimumWidth )
rect.setWidth(m_drawRectMinimumWidth);

if(rect.height() < m_drawRectMinimumHeight)
rect.setHeight(m_drawRectMinimumHeight);

//set the rectangle width with the text item spacing
rect.setWidth(rect.width() + getTextItemSpacing() );

//and return the rectangle
return rect;
}

//the following function is for better collission detection
QPainterPath RootGraphicsItem::shape() const
{
QRectF ellipse_rect = boundingRect();

QPainterPath path;

path.addEllipse(ellipse_rect);

return path;
}



There are some affine transformation issues need to be taken care of - i guess and i am not sure how to do it. Do i have call some translation command before calling the ellipse drawing function ? I tried this as well and it became messier.


Looking forward to some useful hint over this .



Thanks
Sajjad

wysota
8th February 2012, 11:13
And where do you call prepareGeometryChange()?

sajis997
8th February 2012, 11:56
Hi

i have inserted the function call prepareGeometryChange inside the following function at arrow.cpp of the updated diagram scene example to recreate the problem.




void Arrow::updatePosition()
{
prepareGeometryChange();

//declare a new line
QLineF line(mapFromItem(myStartItem, 0, 0), mapFromItem(myEndItem, 0, 0));
setLine(line);
}



And the above function is called as follows:




QVariant DiagramItem::itemChange(GraphicsItemChange change,
const QVariant &value)
{
//if the dialgram items change is about the item positional change
//then we need to notify the component items about the changes
if (change == QGraphicsItem::ItemPositionChange)
{
//all the arrows connected to
//it need to update its position

foreach (Arrow *arrow, arrows)
{
arrow->updatePosition();
}
}

return value;
}




But i am having the same problem - The arrow does not attach to the intersection point. I am attaching all the sources now. I hope that it will be more

illustrative to solve the issue. If i change the code in diagramitem.cpp as follows the problem is solved here as i mentioned in my previous post.



QGraphicsEllipseItem item(-100,-50,200,100);
myPolygon = item.shape().toFillPolygon();


But in my original project, the graphical items bounding rectangles starting point is from (0,0,width,height). And i do want to implement this intersection test there as well. Please make some time to go through this and help me solve the problem.



Regards
Sajjad

wysota
8th February 2012, 12:09
I meant prepareGeometryChange() for your RootGraphicsItem class. Its bounding rect depends on the size of the text (and possibly some other things) yet you never inform graphics view the size of the item might have changed.

sajis997
8th February 2012, 12:25
In the last post i missed to include the source that i did some changes. Sorry.


7377737673787379



Please go through it and suggest me to get it fixed.


Regards
Sajjad

Added after 9 minutes:


I meant prepareGeometryChange() for your RootGraphicsItem class. Its bounding rect depends on the size of the text (and possibly some other things) yet you never inform graphics view the size of the item might have changed.

Yes it is true that the size of the bounding rectangle is based on the size of the text and predefined text spacing. And i am defining the size of the item inside the boundingRect() function, do i need to call the prepareGeometryChange() inside the boundingRect() and even if i do i get the following error:



RootGraphicsItem.cpp:671: error: passing ‘const RootGraphicsItem’ as ‘this’ argument of ‘void QGraphicsItem::prepareGeometryChange()’ discards qualifiers




Regards
Sajjad

sajis997
8th February 2012, 14:42
I call the prepareGeometryhange() inside the definition of boundary rectangle but it gives me the error as follows:



RootGraphicsItem.cpp:668: error: passing ‘const RootGraphicsItem’ as ‘this’ argument of ‘void QGraphicsItem::prepareGeometryChange()’ discards qualifiers


I guess that it is not the right place to call the prepareGeometryChange(), as i am doing it now:



QRectF RootGraphicsItem::boundingRect() const
{

prepareGeometryChange();

//!get the bounding rectangle of the enclosing text
QRectF rect = m_textGraphicsItem->boundingRect();

//the following condition decides if the boundary needs
//to be changed
if( rect.width() < m_drawRectMinimumWidth )
rect.setWidth(m_drawRectMinimumWidth);

if(rect.height() < m_drawRectMinimumHeight)
rect.setHeight(m_drawRectMinimumHeight);

//set the rectangle width with the text item spacing
rect.setWidth(rect.width() + getTextItemSpacing() );

//and return the rectangle
return rect;
}



According to the manual it should be called once the set bounding rectangle is about to change. I am deciding the size before setting the bounding rectangle.

Any more suggestion ?

wysota
8th February 2012, 15:59
Calling that method from within boundingRect() wouldn't make sense. You need to call it when the actual change occurs (like when the text or spacing is changed).

sajis997
8th February 2012, 16:06
Hi

This is what i think as well. I am changing the text later after defining the bounding rectangle.


Could you please figure out any another reason that the arrow item and elliptical item intersection test is not functioning ?



Regards
Sajjad

wysota
8th February 2012, 16:13
Could you please figure out any another reason that the arrow item and elliptical item intersection test is not functioning ?
What's wrong with the original reason? Don't you think we should test one thing at a time?

sajis997
8th February 2012, 17:26
Hi

I am sorry. I did not get your last post. Did i cause something to distract from the main issue here. Let me summarize again:

I am trying to make connections between arrow and elliptical items in my own project and i tried to use the concept of diagramscene example.

I am having trouble to implement it - as the arrow is not properly attached to the elliptical items and they suddenly disappear once i start to move the elliptical items in the scene view.

I recreated the problem in the diagram scene example and posted in the forum for your point of view. All the details are mentioned in the previous posts.

Now please guide me where should i start from to debug this problem ?


Regards
Sajjad

wysota
8th February 2012, 18:03
Hi

I am sorry. I did not get your last post. Did i cause something to distract from the main issue here. Let me summarize again:

I am trying to make connections between arrow and elliptical items in my own project and i tried to use the concept of diagramscene example.

I am having trouble to implement it - as the arrow is not properly attached to the elliptical items and they suddenly disappear once i start to move the elliptical items in the scene view.

I recreated the problem in the diagram scene example and posted in the forum for your point of view. All the details are mentioned in the previous posts.

Now please guide me where should i start from to debug this problem ?


Correct the bounding rect issue as it may have influence on how your scene is rendered in the view. Once that is done and it's not something that causes the misbehaviour, we can look elsewhere. Otherwise you can prepare a minimal compilable example reproducing the problem and we can work on that.

sajis997
8th February 2012, 19:50
Hi

I would like to know what do i have to do to correct the bounding rect issue of the elliptical graphics item. Its bounding rectangle is based on the bounding rectangle of the text graphics item it contains. Text graphics item that is contained inside the elliptical item is in turn the subclass of QTextGraphicsItem. I would like to repeat that once that the bounding rect is defined inside the boundingRect() it is never changed since then and this is why i do not see any reason to call the prepareGeometryChange() function.

Could you please mention what might be wrong in the bounding rect function



QRectF RootGraphicsItem::boundingRect() const
{

prepareGeometryChange();

//!get the bounding rectangle of the enclosing text
QRectF rect = m_textGraphicsItem->boundingRect();

//the following condition decides if the boundary needs
//to be changed
if( rect.width() < m_drawRectMinimumWidth )
rect.setWidth(m_drawRectMinimumWidth);

if(rect.height() < m_drawRectMinimumHeight)
rect.setHeight(m_drawRectMinimumHeight);

//set the rectangle width with the text item spacing
rect.setWidth(rect.width() + getTextItemSpacing() );

//and return the rectangle
return rect;
}


Otherwise i am attaching the files again which is compilable that recreates the problem in another project. All that you need to do is that create another copy of the diagramscene example, remove the diagramscene.h and diagramscene.cpp and add the following files:

7383
7384
7385
7386

And you have add the following line inside the createToolBox() of mainwindow.cpp



layout->addWidget(createCellWidget(tr("Ellipse"),DiagramItem::Ellipse),2,0);


If you mange some time and compile with these added files and the reamaining files as arrived with the example you will see the problem

The arrow is not connected as it is supposed to .


Let me know if you have any trouble to compile them .


Regards
Sajjad

wysota
8th February 2012, 20:10
And what should I be looking at once I start the program? What exactly did you change in those files?

sajis997
9th February 2012, 03:36
Hello ,

Create Two elliptical items in the scene and connect them with a line. Line drawing can be done in one of the two ways. Either you use the one that came along with the original diagram scene example or the one i have added - move the the mouse with the control modifier and the line will be drawn. When you release the control modifier
it will do the usual checking if there is any item under the event position and take the steps to draw the line arrow or not.

Once the items are connected, try to move the elliptical items and then you will see the problem - the arrow is not properly attached to the elliptical items and at times the arrow disappears.


I have removed the diagramscene.h - which was a subclass of QGraphicsScene, instead i have created a class called diagramsceneview - a subclass of QGraphicsView and moved all the functionalities to this class here. You have to remove the diagramscene class from your copy of the diagramscene example as well and add the one i have attached.

Then you have to make the following changes inside th diagramitem.h file



enum DiagramType
{
Step,
Conditional,
StartEnd,
Io ,
Ellipse // add the ellipse type
};


In the constructor of diagramitem.cpp do the following:



case Ellipse:
{
//declare an ellipse with the bounding rectange
// QGraphicsEllipseItem item(-100,-50,200,100);
QGraphicsEllipseItem item(0,0,200,100);
myPolygon = item.shape().toFillPolygon();
}
break;



And at last in the createToolBox() function of mainwindow.cpp add the following:



layout->addWidget(createCellWidget(tr("Ellipse"),DiagramItem::Ellipse),2,0);


So you are good to compile and run and see the problem, the problem is because of the following



// QGraphicsEllipseItem item(-100,-50,200,100);
QGraphicsEllipseItem item(0,0,200,100);


As you can see that i have commented the first line to recreate the problem here which i am having in my own project where i am trying to implement this intersection test between line and polygonal shape. If you uncomment it and then comment the next one instead , everything works just fine. This is where i think is the problem. My question is how do i get rid of this in my projeject?


Let me know how it went along at your side.


Regards
Sajjad

wysota
9th February 2012, 10:55
The problem is I don't know what you modified in those files and comparing them by hand is tedious enough that it prevents me from doing it and comparing them automatically is not possible since you changed formatting of those files.

sajis997
9th February 2012, 11:21
I assume the fact that it did not go well at your side. So please go to the following website and download the .zip file named diagramsceneupdated3.zip

http://www.student.itn.liu.se/~sajis997/diagramsceneupdated3.zip

I hope that file formating issue will not arise anymore and you will be able to edit.

If you manage to run it, please try to add elliptical items and connect them with a arrow and try to move around the scene and you will see the problem.

Let me know if any other issues show up and thank you again for your effort to solve the issue.


Regards
Sajjad

wysota
9th February 2012, 11:24
Let's make it clear -- I am able to run it and I can see the malfunction, the problem is that not knowing what you have changed makes it hard to find the problem. That's why we ask about a minimal compilable example reproducing the problem, not an edited example reproducing the problem :) Create a simple program with two elipses and a line connected to them that reproduces the problem (up to 50 lines of code in total).