Cannot modify Qml propriety from Cpp



  • I've this main.cpp code:
    @int main(int argc, char *argv[])
    {
    QGuiApplication app(argc, argv); //preparo l'applicazione
    QQmlApplicationEngine engine(QUrl("qml/main.qml")); //carico l'interfaccia
    QObject *radice = engine.rootObjects().value(0); //identifico la radice
    QQuickWindow *applicationwindow = qobject_cast<QQuickWindow *>(radice); //acquisisco in C++ l'ogg QML ApplicationWindow
    if ( !applicationwindow )
    {
    qWarning("Error: Your root item has to be a Window.");
    return -1;
    }

    QObject *button = radice->findChild<QObject*>("buttonOpenCloseCom",Qt::FindChildrenRecursively);
    if (button)
    {
        button->setProperty("text", "Open");
        qDebug()<<"find!";
    }
    
    applicationwindow->show();
    return app.exec();
    

    }@

    and this main.qml file:
    @import QtQuick 2.1
    import QtQuick.Controls 1.0
    import QtQuick.Controls.Styles 1.0
    import QtQuick.Layouts 1.0

    ApplicationWindow
    {
    id: applicationwindow;
    /Interface config/
    title: appname
    property int margin: 11
    property string appname: "Controller 0.1"
    property int coordsFontSize: 25
    property string buttonComText: "Open/Close"
    //width: mainLayout.implicitWidth + 2 * margin
    //height: mainLayout.implicitHeight + 2 * margin
    width: 1024
    height: 768
    minimumWidth: 1024
    minimumHeight: 768

    RowLayout
    {
        id: mainLayout
        anchors.fill: parent
        anchors.margins: margin
        Layout.fillWidth: true
    
        ColumnLayout
        {
            id: leftColumn
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 0
            anchors.top: parent.top
            anchors.left: parent.left
            Layout.fillWidth: false
            Layout.preferredWidth: parent.width/2
            //Layout.preferredHeight: parent.height/2
    
            GroupBox
            {
                id: comGroupBox
                title: "COM Layer"
                Layout.fillWidth: true
    
                RowLayout
                {
                    id: rowlayout1
                    anchors.top: parent.top
                    anchors.fill: parent
                    anchors.margins: 20
    
    
                    spacing: 5
    
                    ComboBox
                    {
                        id: comboComs
                        model: [ "COM1", "COM2", "COM3" ]
                        function test()
                        {
                            console.log("TEST OK");
                        }
                    onClipChanged: {console.log("azz")}
                    }
    
                    Button
                    {
                        id: buttonOpenCloseCom
                        objectName:  buttonOpenCloseCom
                        text:applicationwindow.buttonComText
                        enabled: true
                    }
    
                }
            }
    }
    

    }@

    I need to change the text of the button that has the objectName proprety "buttonOpenCloseCom", but the code defined in main.cpp doesn't work, and I'm not able to understand why. I've followed examples like "this":http://qt-project.org/doc/qt-5.1/qtqml/qtqml-cppintegration-interactqmlfromcpp.html but it seem that the button object is not found by the findChild method... infact the qDebug print is not performed...
    Can anyone help me?


  • Moderators

    I guess you need to set that property after even loop is started in app.exec().

    Otherwise, the code seems to be correct (although there is no need to modify buttonOpenCloseCom, when you can just modify buttonComText in ApplicationWindow).



  • Hi, thanks for the answer.
    I've changed the code:
    @int main(int argc, char *argv[])
    {
    QGuiApplication app(argc, argv); //preparo l'applicazione
    QQmlApplicationEngine engine(QUrl("qml/main.qml")); //carico l'interfaccia
    QObject *radice = engine.rootObjects().value(0); //identifico la radice
    QQuickWindow *applicationwindow = qobject_cast<QQuickWindow *>(radice); //acquisisco in C++ l'ogg QML ApplicationWindow
    if ( !applicationwindow )
    {
    qWarning("Error: Your root item has to be a Window.");
    return -1;
    }
    applicationwindow->show();
    return app.exec();

    QObject *button = radice->findChild<QObject*>("buttonOpenCloseCom",Qt::FindChildrenRecursively);
    if (button)
    {
        button->setProperty("text", "Open");
        qDebug()<<"found!";
    }
    else
    {
        button->setProperty("text", "Open");
        qDebug()<<"not found!";
    }
    

    }@

    but there is no output.
    The problem persists!

    I've also tried to change the buttonComText in ApplicationWindows, but the result is the same.



  • Try this:
    objectName: "buttonOpenCloseCom"



  • There is yet the objectName proprety.
    I've tried this solution... but doesn't work.
    [quote author="wspilot" date="1376930837"]Try this:
    objectName: "buttonOpenCloseCom"[/quote]



  • In your code it is still an identifier/var or whatever, but not a string
    objectName: buttonOpenCloseCom
    not
    objectName: “buttonOpenCloseCom”



  • Excuseme but in the code:
    @
    Button
    {
    id: buttonOpenCloseCom
    objectName: buttonOpenCloseCom
    text:applicationwindow.buttonComText
    enabled: true
    }
    @

    objectName: “buttonOpenCloseCom” there is![/quote]

    what is the problem you talk about?!


  • Moderators

    Put it in quotes: ". Not just string but "string".



  • @ Button
    {
    id: buttonOpenCloseCom
    objectName: "buttonOpenCloseCom"
    text:applicationwindow.buttonComText
    enabled: true
    }@



  • I've understand what you mean, and I've tried with the correction, but the result is the same as before.
    Debugging i've see that the root object is correctly the "applicationwindow",
    but when I try to find the child, it fails and return a null pointer...
    in "this":http://qt-project.org/doc/qt-5.1/qtqml/qtqml-cppintegration-interactqmlfromcpp.html#loading-qml-objects-from-c reference it used QQuickView, and not QQuickWindow to handle the root object...
    Could it be a problem?
    If yes, how can I resolve it? any suggestions?



  • The problem is that you make the change after the return() statement.
    Nothing after that will be executed.



  • I've modified the code:
    @int main(int argc, char *argv[])
    {
    QGuiApplication app(argc, argv); //preparo l'applicazione
    QQmlApplicationEngine engine(QUrl("qml/main.qml")); //carico l'interfaccia
    QObject *radice = engine.rootObjects().value(0); //identifico la radice
    QQuickWindow *applicationwindow = qobject_cast<QQuickWindow *>(radice); //acquisisco in C++ l'ogg QML ApplicationWindow
    if ( !applicationwindow )
    {
    qWarning("Error: Your root item has to be a Window.");
    return -1;
    }
    QObject button = radice->findChild<QObject>("buttonOpenCloseCom",Qt::FindChildrenRecursively);
    if (button)
    {
    button->setProperty("text", "Open");
    qDebug()<<"found!";
    }
    else
    {
    button->setProperty("text", "Open");
    qDebug()<<"not found!";
    }

    applicationwindow->show();
    return app.exec();
    

    }@

    but is the same as before...
    [quote author="mranger90" date="1376947874"]The problem is that you make the change after the return() statement.
    Nothing after that will be executed.[/quote]


  • Moderators

    One drawback of QML is that it's mightily hard to explain certain things... In order for this to work (IMO) you need to do that property manipulation outside of "main.cpp":https://github.com/sierdzio/closecombatfree/blob/master/src/ccfmain.cpp so for example in a QObject that gets initialised somewhere later. Same as with QWidgets or console apps in Qt: you need to have a working event loop for moc to work.

    One possible alternative would be to modify the property using Qt::QueuedConnection, or the infamous singleshot QTimer.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.