Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Busy indicator in QML
QtWS25 Last Chance

Busy indicator in QML

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
qmlc++qthreadbusy indicator
5 Posts 3 Posters 2.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    VinayBalajiRajputh
    wrote on last edited by VinayBalajiRajputh
    #1

    I am trying to implement busy indicator in my application. But the current implementation is not working correctly.

    ---Main.qml----

    import QtQuick 2.4
    import QtQuick.Controls 1.3
    import QtQuick.Window 2.2
    import QtQuick.Dialogs 1.2
    
    ApplicationWindow {
        title: qsTr("Hello World")
        width: 640
        height: 480
        visible: true
    
    BusyIndicator {
     id: indicator
     running: false
    }
    
    MainForm {
        anchors.fill: parent
        button1.onClicked: {
            indicator.running = true
            console.info(indicator.running)
    
            obj.runWorkerFunction()
    
            indicator.running=false
            console.info(indicator.running)
        }
    }
    }
    
    ---Testclass.cpp----
    
    #include "testclass.h"
    #include <QDebug>
    #include <QThread>
    
    TestClass::TestClass(QObject *parent) : QObject(parent)
    {
    
    }
    TestClass::~TestClass(){
    }
    
    void TestClass::workerFunction() {
        for(int i = 0; i < 1000; i++){
                qDebug() << i;
        }
     qDebug() << "Done";
    }
    
    void TestClass:: runWorkerFunction(){
    //    QThread* thread = QThread::create([this]() {
    //                   workerFunction();
    //                   emit workerFinished();
    //                });
    //    thread->start();
        workerFunction();
    }
    ---Main.cpp
    
    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "testclass.h"
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        TestClass obj;
        QQmlApplicationEngine engine;
        QQmlContext *context = engine.rootContext();
        context->setContextProperty("obj", &obj);
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        return app.exec();
    }
    

    I have tried using Thread which is currently commented out, but busy indicator does not work. The goal is to show the indicator only during the worker thread performs heavy calculation. Additionally with Connections binding I could not make it work. Can anyone help me out with this problem.

    Thank you

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      Which part does not work?

      • openFile is never called
      • thread is never started
      • busy indicator never stops running
      • something else?

      (Z(:^

      1 Reply Last reply
      0
      • V Offline
        V Offline
        VinayBalajiRajputh
        wrote on last edited by
        #3

        Hi @sierdzio ,

        • Open file is called
        • Thread is started
        • Busy indicator never starts after finishing the openFile function i think for very small duration it sets to true and then quickly back to false in the callback. But this is not seen visually. I have tried adding log messages and it seems only after the function open file is finished all the messages are logged
        1 Reply Last reply
        0
        • V Offline
          V Offline
          VinayBalajiRajputh
          wrote on last edited by
          #4

          I have updated my post, to make it more clear and code testable

          Gojir4G 1 Reply Last reply
          0
          • V VinayBalajiRajputh

            I have updated my post, to make it more clear and code testable

            Gojir4G Offline
            Gojir4G Offline
            Gojir4
            wrote on last edited by
            #5

            @VinayBalajiRajputh said in Busy indicator in QML:

            I have tried adding log messages and it seems only after the function open file is finished all the messages are logged

            IMHO that's the expected behavior as you are not using thread and make everything in a function the events are blocked until execution is finished.

            What you can do if to provide a property from TestClass whic indicates if thread is running, and then bind this property with the BusyIndicator.

            But just a warning about the thread part, as I'm not an expert I reused your code with some modification for creating and starting the thread. But I don't think this is the correct way to use threads. I recommend that you read carefully QThread documentation, there is a nice example of how to use worker objects by moving them to the thread using QObject::moveToThread(). There are also other ways like QThreadPool and QRunnable or QtConcurrent.
            There are also plenty of post on this forum and many others about how to use QThread

            import QtQuick 2.10
            import QtQuick.Window 2.10
            
            //Post: https://forum.qt.io/topic/104906/busy-indicator-in-qml/3
            
            import QtQuick 2.4
            import QtQuick.Controls 1.3
            import QtQuick.Window 2.2
            import QtQuick.Dialogs 1.2
            
            ApplicationWindow {
                title: qsTr("Hello World")
                width: 640
                height: 480
                visible: true
            
                Connections{
                    target: obj
                    onIsRunningChanged: console.log("Running: " + obj.isRunning)
                }
            
                BusyIndicator {
                    id: indicator
                    running: obj.isRunning
                    anchors.centerIn: parent
                }
            
                Button {
                    text: "start"
                    anchors.top: parent.top
                    anchors.horizontalCenter: parent.horizontalCenter
                    onClicked: obj.runWorkerFuntion()
                }
            }
            

            c++

            //testclass.h
            #ifndef TESTCLASS_H
            #define TESTCLASS_H
            
            #include <QObject>
            
            class TestClass : public QObject
            {
                Q_OBJECT
            
                Q_PROPERTY(bool isRunning READ isRunning NOTIFY isRunningChanged)
                bool m_isRunning = false;
            
                void workerFunction();
            
            public:
                explicit TestClass(QObject *parent = nullptr);
            
                bool isRunning() const;
            
            public slots:
                void runWorkerFuntion();
            
            signals:
                void isRunningChanged(bool isRunning);
            
            protected slots:
                void setIsRunning(bool isRunning);
                void threadStarted();
                void threadFinished();
            };
            
            #endif // TESTCLASS_H
            
            
            testclass.cpp
            #include "testclass.h"
            
            #include <QThread>
            #include <QDebug>
            TestClass::TestClass(QObject *parent) : QObject(parent)
            {}
            
            bool TestClass::isRunning() const
            {
                return m_isRunning;
            }
            
            void TestClass::runWorkerFuntion()
            {
                qDebug() << "runWorkerFuntion() from main thread: " << QThread::currentThreadId();
            
               // /!\ THIS IS NOT A GOOD WAY TO USE THREAD
                QThread* thread = QThread::create([this](){
                    workerFunction();
                });
                connect(thread, &QThread::started, this, &TestClass::threadStarted);
                connect(thread, &QThread::finished, this, &TestClass::threadFinished);
                connect(thread, &QThread::finished, thread, &QObject::deleteLater);
                thread->start();
            
            }
            
            void TestClass::workerFunction()
            {
                qDebug() << "workerFunction() from thread:        " << QThread::currentThreadId();
                QThread::sleep(1);
            }
            
            void TestClass::setIsRunning(bool isRunning)
            {
                if (m_isRunning == isRunning)
                    return;
            
                m_isRunning = isRunning;
                emit isRunningChanged(m_isRunning);
            }
            
            void TestClass::threadStarted()
            {
                setIsRunning(true);
            }
            
            void TestClass::threadFinished()
            {
                setIsRunning(false);
            }
            
            

            console output:

            runWorkerFuntion() from main thread:  0x4228
            workerFunction() from thread:         0x15a4
            qml: Running: true
            qml: Running: false
            
            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved