[SOLVED] Qt5 Android: QML & C++ communication
-
Hi,
I'M trying to adjust my existing QML/C++ app for Android and have following problem:this is my exisitng Qt4 code which works on win32 & linux x86/x86_64:
@
QObject * btn = this->rootObject()->findChild<QObject*>("login_btn");
if(btn != NULL)QObject::connect(btn, SIGNAL(clicked(const QString &, const QString &)),this->crm, SLOT(Login(const QString &, const QString&)));
else qWarning() << "Can't find login button object on splash screen";
@"this" is subclass of QDeclarativeView. I've changed it to QQuickView because of Qt5. So, on Android with Qt5 this code doesn't work and always fails to qWarning.... I have checked rootObject()->children() list and all objects have empty objectName().
Can someone confirm this? Is there new way to find objects in qml in Qt5?
-
OK, with Qt 5.1.2 on desktop environment same problem... objectNames are empty...
-
Hi,
Strange... Do you have the same objects count in you view as in your QML ? Are the names really empty or just different ?
Although I'm sure you know directly accessing QtQuick components is clearly not the "recommanded way" of using QtQuick, I doubt they would have deliberatly broken the findChild method.
-
Why do you think it's not recommended? It's one of the beauties of meta object system... For me it still works, although the newest Qt I've tried is 5.1.0.
-
Well because that kinda break the C++/QML separation, and is do-able by keeping that separation. Actually I didn't noticed there was no QML modification at all from the C++ side , so that's not a big deal.
And anyway if sierdzio says it's alright, I'm not gonna contradict him ;).
-
[quote author="Adrien Leravat" date="1378886364"]Hi,
Strange... Do you have the same objects count in you view as in your QML ? Are the names really empty or just different ?
Although I'm sure you know directly accessing QtQuick components is clearly not the "recommanded way" of using QtQuick, I doubt they would have deliberatly broken the findChild method.
[/quote]
They are emtpy, all of them... but in qml file id is set for most of them... and yes, item count is the same....
directly accessing QtQuick components is clearly recommendet way since was introduced in Qt4 for QML/C++ communication.[quote author="sierdzio" date="1378886962"]Why do you think it's not recommended? It's one of the beauties of meta object system... For me it still works, although the newest Qt I've tried is 5.1.0.[/quote]
Have tried it with Qt 5.0.1 SDK for linux, and got same thing... objectNames are empty.... Maybe I'm missing something in my code....
qml file:
@
import QtQuick 2.0Rectangle
{
id: gui_mainItem { id: item_list anchors.top: item_search.bottom anchors.left: parent.left anchors.bottom: parent.bottom width: parent.width*0.9 ListView { id: list_contacts anchors.fill: item_list model: ContactsModel delegate: contactDelegate highlight: highlight highlightFollowsCurrentItem: false focus: true Component.onCompleted: { positionViewAtIndex(1, ListView.Beginning) } } } Item { id: item_search x: 0 y: 0 width: parent.width height: gui_main.width>gui_main.height?parent.height*0.05:parent.height*0.03 signal searchFor(string str) Rectangle { anchors.fill: item_search color: "darkblue" Rectangle { anchors.fill: parent anchors.margins: 4 color: "white" radius: 2 TextInput { id: item_search_text_input anchors.fill: parent anchors.leftMargin: 5 anchors.rightMargin: 5 font.pixelSize: parent.height-8 text: qsTr("") Keys.onReturnPressed: { item_list.focus = true; Qt.inputMethod.hide(); item_search.searchFor(text); } } } } }
...
@QQuickView subclass:
@
CRMGUI::CRMGUI(QWindow *parent):
QQuickView(parent),
m_load_counter(0),
crm(new CRMWebServices(this)),
m_model(new CRMContactsListModel(this)),
m_sort_model(new CRMContactsSortModel(this))
{
connect(this->engine(), &QQmlEngine::quit, this, &CRMGUI::close);
this->setResizeMode(QQuickView::SizeRootObjectToView);this->m_sort_model->setSourceModel(this->m_model); QQmlContext * context = this->rootContext(); context->setContextProperty("scale",1 /* Calculate scale value for each display size */); context->setContextProperty("viewerWidget",this); context->setContextProperty("ContactsModel", this->m_sort_model); connect(this, &CRMGUI::statusChanged, this, &CRMGUI::viewStatusChanged);
}
void CRMGUI::setMainQmlFile(const QString &file)
{
this->m_main_qml = QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), file);
if(!QFileInfo(this->m_main_qml).exists())
{
this->m_main_qml = QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), file);
if(!QFileInfo(this->m_main_qml).exists())this->m_main_qml = file;
}#ifdef Q_OS_ANDROID
setSource(QUrl(QLatin1String("assets:/")+this->m_main_qml));
#else
setSource(QUrl::fromLocalFile(this->m_main_qml));
#endif
}void listObjs(QObject * obj)
{
QObjectList list = obj->children();
foreach(QObject * obj, list)
{
qDebug() << obj->objectName();
listObjs(obj);
}
}void CRMGUI::viewStatusChanged(QQuickView::Status status)
{
if(status == QQuickView::Ready)
{QObjectList list = this->rootObject()->children(); foreach(QObject * obj, list) { qDebug() << obj->objectName(); listObjs(obj); } QObject * search_item = this->rootObject()->findChild<QObject *>("item_search"); if(search_item != 0) { connect(search_item, SIGNAL(searchFor(QString&)), this, SLOT(Search(QString&))); }else qDebug() << "Object not found"; }
}
@
main loop:
@
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);CRMGUI viewer;
viewer.setMainQmlFile(QStringLiteral("qml/CRM/main.qml"));
viewer.show();return app.exec();
}
@item_search item is exist and id is set in qml... I'm searching for it after QQuickView becomes Ready... no idea what's wrong...
-
Ah, ok it's clear now. QML's id is not the same as objectName. Ids are internal QML stuff, completely invisible in C++ (and outside of QML scope, even to other Components). If you want to use meta object system, you have to specify object name by hand:
@
Item {
id: myItem
objectName: "myItem"
}
@ -
**** i knew I have missed something.... Thanks sierdzio!
-
No, it's stored internally in private parts of QQuickItem. There is no way to get it in C++ without changing Qt library source code.
This has been raised on Qt bugtracker and mailing lists, but IIRC devs are reluctant to change it, due to some technicalities I don't remember right now.
On the plus side, this lowers meta object overhead: only those you explicitly name using "objectName" are visible.
-
Thank you for clarification!