PDA

View Full Version : QGraphicsItem zValue question



d_stranz
29th April 2012, 17:46
I need some help understanding how QGraphicsItem::zValue() works in relationship to clipping. I have a scene with many text labels (QGraphicsSimpleTextItem-based). Because some sections of the scene can have many labels, it is possible for the labels to overlap. I am using QGraphicsItem::setZValue() to put a z-ordering on the labels, with more "important" labels having higher z values. All of the labels are siblings and children of a single parent QGraphicsItem. The labels can't be opaque; the scene information "behind" the labels has to show through.

I am having several problems:

- all of the items are painted, no matter what their z-value, so the result is a mess of overlapped labels.
- if I set QGraphicsItem::ItemClipsToShape for the labels, none of them are drawn, even ones that don't overlap
- if I call QGraphicsItem::collidingItems( Qt::IntersectsItemBoundingRect ) on any one of them, I get a list that contains only the parent or other non-label items in the scene.

If I try with this code ("textItems" is a std::vector<> that contains all of the siblings with the QGraphicsSimpleTextItem::Type ):



std::vector< QGraphicsItem * >::iterator it = textItems.begin();
std::vector< QGraphicsItem * >::iterator eIt = textItems.end();
while ( it != eIt )
{
QGraphicsItem * pItem = *it++;
if ( pItem->isVisible() )
{
std::vector< QGraphicsItem * >::iterator oIt = it;
while ( oIt != eIt )
{
QGraphicsItem * pOther = *oIt++;
if ( pItem->collidesWithItem( pOther, Qt::IntersectsItemBoundingRect ) )
{
if ( pItem->zValue() < pOther->zValue() )
{
pItem->setVisible( false );
break;
}
else
pOther->setVisible( false );
}
}
}
}


then the collidesWithItem does return true for many labels, but I still end up with overlaps in some places anyway, and this code is very, very slow since there are thousands of labels. It gets executed with every scene transformation (for example, zooming or panning).

Is there some way of getting QGraphicsScene / QGraphicsView to do this clipping automatically?

Spitfire
1st May 2012, 13:48
I think z-value has nothing to do with clipping, it's just an order in which items are drawn on the screen.

Also I'm not sure what you're trying to do.
You're talking about clipping but you hide items with lower z-value.

Do you want part of the labels 'below' to be visible when obscured by other label?
Or do you want to hide labels that are even partially obscured by other labels?

To be able to help you, you need to share little more of your requirements.
Is the labels position static or dynamic?
Is the labels geometry static or dynamic (changing label content changes label geometry)?
What should happen if two labels of the same z-order overlap?

I would also question why all labels (thousands?) have the same parent item?
Can't you break them into smaller groups and investigate which one should be visible when one item in the group changes.
Also, because when zooming or panning, items themself do not change their geometry, none of the calculations you did to figure out what to show should be done again.