Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to update QML Items from non-main thread in C++ correct way?



  • I am trying update the QML scene from QtConcurrent::run thread in C++. I have thread like this

    QtConcurrent::run([host, port,username,password,this](){
        // some networking and socket stuff  
        if(socket->waitForConnected()){
            if(access == Protocol::PHAKU){
                socket->deleteLater();
                socket = nullptr;
                showWithError("password and username did not matched");
            }
    });
    

    and showWithError function is like this:-

    void Login::showWithError(QString error) {
        loginRect->setProperty("visible","true");
        loginRect->setProperty("enabled","true");
        lodingAnime->setProperty("running",false);
        errorMsg->setProperty("text",error);
        submit->setProperty("visible",true);
    }
    

    I have already filled the values of above variables with qml items in constructor like this

    Login::Login(QObject *login) : QObject(nullptr), login(login) {
        lodingAnime = login->findChild<QObject*>("lodingAnime");
        submit = login->findChild<QObject*>("submit");
        errorMsg = login->findChild<QObject*>("errorMsg");
        loginRect = login->parent();
    }
    

    When Run the app, It works perfectly fine. But I get same multiple warnings like this one:-

    Updates can only be scheduled from GUI thread or from
    QQuickItem::updatePaintNode()

    Should I ignore this warning ?

    I tried replacing pure function calls with signals and slots but I am getting segmentation fault
    like this:-

    connect(this,&Login::showWithError_,&Login::showWithError_);
    

    somewhere in code:-

    emit showWithError_("bla bla some error");


  • Solved it, My bad. I was connecting signal back to signal itself

    needed to change

    connect(this,&Login::showWithError_,&Login::showWithError_);
    

    to

    connect(this,&Login::showWithError_,&Login::showWithError);
    


  • I'd be careful just because of my own assumptions / experience, it sounds like you're setting up a landmine for later, I don't know because I just skimmed your issues, I can't tell enough for a proper context but I can recall the bug report that I found when I did.

    You might find this useful too: https://bugreports.qt.io/browse/QTBUG-43230

    Ulf Hermann added a comment - 18 Mar '19 9:19 PM
    Note that exposing objects that live in a different thread as the QML engine via context properties is dangerous to begin with. You cannot safely access properties or call methods of such objects from QML. I really recommend proxying the signals through a separate object that lives in the engine thread.

    Ulf Hermann added a comment - 30 Apr '19 10:02 PM
    The bad idea is not actually the connection. The fact that the connection behaves in the way described here is just the consequence of the fact that you're exposing an object from a different thread. The QML language has no concept of threads (besides WorkerScript, but that is a different beast), so exposing the C++ threading model to it via context properties is a bad idea. The engine does not magically provide thread safety for otherwise unsafe operations and it needs to inspect the objects given to it as context properties.
    Please make sure everything you expose to a particular engine lives in the same thread. Otherwise all bets are off anyway.