PDA

View Full Version : GraphicsView: Notifying geometry change to parent group



Gopala Krishna
28th July 2007, 19:29
Hi,
I have custom QGraphicsTextItem whose instances are added to a QGraphicsItemGroup subclass. The textitem has TextEditorInteraction as textinteraction flags.

Now whenever the size of the textitem changes due to text entered by keyboard the group doesn't seem to update its childrenRect and hence when the group is selected later , the selected rect remains smaller and the some part of text of text item remains outside the selected rect.
For now i have this hack


void PropertyText::focusOutEvent(QFocusEvent *event)
{
QGraphicsTextItem::focusOutEvent(event);
trimText();
if(group()) {
QGraphicsTextItem *dummy = new QGraphicsTextItem();
group()->addToGroup(dummy);
group()->removeFromGroup(dummy);
delete dummy;
}
}


Can this be regarded as a bug in Qt ? Also are there any better/efficient workarounds ?

I'm using Qt-4.3 - x11

marcel
28th July 2007, 19:44
You're correct, it seems like the itemsBoundingRect in QGraphicsItemGroupPrivate is updated only when adding/removing items from the group.

Couldn't you adjust the geometry of the group after you finish editing the inner text item?
I think a union would suffice : groupBounds = groupBounds | textItemBounds.

Regards

marcel
28th July 2007, 19:52
Even better, I think you can assign QGraphicsItem::childrenBoundingRect to the group's geometry directly. No additional calculations needed.
That is how they do it. Well, not exactly like that :) :


void QGraphicsItemGroup::addToGroup(QGraphicsItem *item)
{
Q_D(QGraphicsItemGroup);
if (!item) {
qWarning("QGraphicsItemGroup::addToGroup: cannot add null item");
return;
}
if (item == this) {
qWarning("QGraphicsItemGroup::addToGroup: cannot add a group to itself");
return;
}

QTransform oldSceneMatrix = item->sceneTransform();
item->setPos(mapFromItem(item, 0, 0));
item->setParentItem(this);
item->setTransform(oldSceneMatrix
* sceneTransform().inverted()
* QTransform().translate(-item->x(), -item->y()));
item->d_func()->setIsMemberOfGroup(true);
prepareGeometryChange();
d->itemsBoundingRect |= (item->transform() * QTransform().translate(item->x(), item->y()))
.mapRect(item->boundingRect() | item->childrenBoundingRect());
update();
}


As you can see, the entire geometry update is done in one line.

Regards

Gopala Krishna
29th July 2007, 14:55
But the itemsBoundRect variable of the group is private and isn't accesible at all. So how do i assign the children's bounding rect to groups item bound rect?

marcel
29th July 2007, 16:40
Override its boundingRect function and always return childrenBoundingRect().
Well, you can cache this value(for speed purposes, if you have a lot of objects in the group) and invalidate it, I don't know, for example when the text item's geometry changes.

Anyway, by default QGraphicsItemGroup::boundingRect returns the d->itemsBoundingRect from QGrahicsItemGroupPrivate.

This should work.

Regards.

Gopala Krishna
29th July 2007, 16:42
Yeah caching is needed. I'll see which hack amongst these to use.
But can this be regarded as qt bug ?

marcel
29th July 2007, 16:49
Yeah caching is needed. I'll see which hack amongst these to use.
But can this be regarded as qt bug ?

I don't know. Pretty hard to say. Looking at the Qt sources it doesn't seem like something was forgotten or misplaced.
It appears more like it was intended behavior. At least to me.

I wonder if Illustrator or InDesign resize their groups when their children's geometry changes. I am not at work now, so I cannot say for sure.
But I can remember pretty well that they do.

Regards

Gopala Krishna
29th July 2007, 16:54
Thanks marcel for your insights :)
I'd say adding a method to recalculate boundingrect to the itemgroup will do the trick.

Gopala Krishna
12th August 2007, 12:04
Unfortunately this won't be fixed even in future versions of qt :(
task tracker (http://trolltech.com/developer/task-tracker/index_html?method=entry&id=158430)