PDA

View Full Version : Weird metaObject->className extension for QML "ghost"-items



sedi
13th September 2015, 14:12
Hi,
I am trying to implement a simple collision detection. I am experiencing some strange behaviour with items that should not exist and are not visible (while invisibly having a location on the screen, see below) - but are found while iterating through QQuickWindow::contentItem's childItems.

I do find the expected Items:

CustomButton_QMLTYPE_17
Ok, that looks reasonable.
The unexpected Items go by this name:

CustomButton_QMLTYPE_17_QML_34

Where does the _QML_34 come from? Are they "invalid"/"old" in any way, just not yet deleted by QML?

I should add, that both numbers (here 17/34) change every time I run the program, (e.g. 67/72, 63/68, 45/62). The numbers seem to be somewhat random, the latter being always higher than the first. While the program is running, they stay constant.

For my view I am using a c++-model-driven QML Repeater which uses a rather complex "CustomButton.qml" as a delegate. Those CustomButtons are built from my own "CollidingItem" class, which inherits from QQuickItem. Works well.
collidingquickitem.h:

class CollidingQuickItem: public QQuickItem
{
Q_OBJECT
public:
CollidingQuickItem();
...

CustomButton.qml:

CollidingQuickItem {
id: personButtonBasis
objectName: "unknownCustomButton"
x: 0
y: 0
width: 100
height: 100
....
ClassroomScene.qml:


...
Repeater {
id: personRepeater
model: groupContent.personButtonContents
delegate: CustomButton {
id: customButtonDelegate
objectName: personRepeater.model[index].nameTop+" "+personRepeater.model[index].nameBottom
...
x: personRepeater.model[index].position.x
y: personRepeater.model[index].position.y
height: 90
width: 90
...
}

}

To find collisions I am crawling through the childItems of QQuickWindow::contentItem, to find all "CollidingQuickItem"-Items, yet without actual collision testing. After this, the resultList contains both expected and unexpected items:

QList<QQuickItem *> Controller::findAllCollidingChildItemsRecursively( QQuickItem *item)
{
QList<QQuickItem*> resultList;
if (!item) {
return resultList;
}
bool isCollider=(dynamic_cast<CollidingQuickItem*>(item));
if ((isCollider)&&(!resultList.contains(item))) {
resultList.append(item);
//no further checking
} else {
foreach (QQuickItem* childItem, item->childItems()) {
resultList.append(findAllCollidingChildItemsRecurs ively(childItem));
}
}
return resultList;
}

The actual collisionCheck reveals the strange "ghost"-Items that I've never (willingly) instantiated, mainly in the upper left of the screen:

QList<QQuickItem *> Controller::itemsCollidingWith(QRectF rect)
{
QList<QQuickItem *> resultList;
QQuickWindow* w = this->topLevelWindow();
foreach (QQuickItem* i, findAllCollidingChildItemsRecursively(w->contentItem())) {
if (rect.intersects(QRectF(i->x(),i->y(),i->width(),i->height()))) {
resultList.append(i);
qDebug()<<"Detection for "<<i->objectName()<<" / "<<i->metaObject()->className();
qDebug()<<typeid(i).name();
}

}
return resultList;
}

Interestingly, the typeId is always the same, the className differs between those items that are visible and should be there - and the others.
Normal output (hitting a visible item):

Detection for "Carsten Ernst" / CustomButton_QMLTYPE_17
P10QQuickItem
Unexpected output (testing an empty area on the top / topLeft of the screen):

"unknownCustomButton" / CustomButton_QMLTYPE_17_QML_34
P10QQuickItem
There are several of these "unknownCustomButton"s.

Any information about QML's className generation or a possible origin of those items would be cool.

anda_skoa
13th September 2015, 17:18
Do you have any local properties in the delegate?
I.e. something that would require the QML engine to create a new type for each delegate instance.

Btw, model data is usually accessed directly through "model.propertyName" or "modelData" (depending on whether this is an actual model or a list of values.

Also, while not answering your question, one thing you could do it to let the CollidingQuickItem constructor register the instance at some global/singleton object and the destructor unregistring.
That way you would never have to search for them.

Cheers,
_

sedi
13th September 2015, 21:48
Thank you, anda_skoa, for your answer!

While playing around with the ideas I took from your post, I have actually found the somewhat embarrassing reason for the "ghost" items - in Layer 8...

There are some instances of a qml subclass of those CustomButtons, that live within another item's area. Thus their positions are relative to that item - not relative to the screen. I have checked collisions with their verbatim x and y values, subsequently getting "hits" in the upper left area of the screen (where they are not located - their parent item lives at the screen's bottom). So I thought I'd hit a "ghost", which I didn't.

Given this, the _QML_*-Extension obviously reflects being a qml subclass of the _QMLTYPE_*.

The idea to register the instances from the constructor of CollidingQuickItem is cool! As my collision checking is on user interaction only, it is time-uncritical and I favour the crawling over the bookkeeping. In other situations, though, I'll definitely heed that advice!

Thank you very much for your time!