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. How to update a text value from C++ dynamic ..
QtWS25 Last Chance

How to update a text value from C++ dynamic ..

Scheduled Pinned Locked Moved Solved QML and Qt Quick
13 Posts 3 Posters 6.7k 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.
  • R Offline
    R Offline
    Ritchie
    wrote on last edited by
    #1

    Hello,

    I am trying to update a Text value from C++, but the value does not change his value in the QML
    code. Within the backend class the value is updated correctly.

    QML Definition

    import QtQuick 2.7
    import QtQuick.Controls 2.0 as QQ2
    import "../Style"
    import name.backend 1.0
    
    ..
    ..
                    Text {
                        id: txtLatitude
                        anchors.horizontalCenter: parent.horizontalCenter
                        text: qsTr("Longitude: ") + backend.Latitude
                        font.pixelSize: UIStyle.fontSizeS
                        font.italic: true
                        color: UIStyle.colorQtGray3
                        onTextChanged:
                            {
                            txtLatitude.text = qsTr("Longitude: ") + backend.Latitude
                            }
                    }
    

    Backend definition file

    #include <QObject>
    #include <QString>
    #include <QGeoPositionInfo>
    
    class BackEnd : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString Latitude READ Latitude NOTIFY LatitudeChanged)
    public:
        explicit BackEnd(QObject *parent = nullptr);
        void        setPosition(QGeoPositionInfo);
        QString     Latitude(void);
    signals:
        void       LatitudeChanged();
    private:
        QString     m_Latitude;
    };
    

    Class BackEnd CPP File

    #include   <QString>
    #include "backend.h"
    
    BackEnd::BackEnd(QObject *parent) :
        QObject(parent)
    {
        m_Latitude="--.----";
    }
    
    QString BackEnd::Latitude(void)
    {
        return m_Latitude;
    }
    
    void BackEnd::setPosition(QGeoPositionInfo Info)
    {
       double  dValue;
       dValue = Info.coordinate().latitude();
       QString sValue = QString::number(dValue,'f',4);
    
       m_Latitude = sValue;
       emit LatitudeChanged();
    }
    

    But the value on the screen is always "Longitude: --.----".

    The value in the BackEnd-Class m_Latitude is updated correctly.
    The value "backend.Latitude" has always "--.----".

    The base code of my QML Application is starting with the sample "wearable" Sample from here

    Where is my fault ?

    Best regards and thanks for any help
    R.

    E 1 Reply Last reply
    0
    • R Ritchie

      Hello,

      I am trying to update a Text value from C++, but the value does not change his value in the QML
      code. Within the backend class the value is updated correctly.

      QML Definition

      import QtQuick 2.7
      import QtQuick.Controls 2.0 as QQ2
      import "../Style"
      import name.backend 1.0
      
      ..
      ..
                      Text {
                          id: txtLatitude
                          anchors.horizontalCenter: parent.horizontalCenter
                          text: qsTr("Longitude: ") + backend.Latitude
                          font.pixelSize: UIStyle.fontSizeS
                          font.italic: true
                          color: UIStyle.colorQtGray3
                          onTextChanged:
                              {
                              txtLatitude.text = qsTr("Longitude: ") + backend.Latitude
                              }
                      }
      

      Backend definition file

      #include <QObject>
      #include <QString>
      #include <QGeoPositionInfo>
      
      class BackEnd : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(QString Latitude READ Latitude NOTIFY LatitudeChanged)
      public:
          explicit BackEnd(QObject *parent = nullptr);
          void        setPosition(QGeoPositionInfo);
          QString     Latitude(void);
      signals:
          void       LatitudeChanged();
      private:
          QString     m_Latitude;
      };
      

      Class BackEnd CPP File

      #include   <QString>
      #include "backend.h"
      
      BackEnd::BackEnd(QObject *parent) :
          QObject(parent)
      {
          m_Latitude="--.----";
      }
      
      QString BackEnd::Latitude(void)
      {
          return m_Latitude;
      }
      
      void BackEnd::setPosition(QGeoPositionInfo Info)
      {
         double  dValue;
         dValue = Info.coordinate().latitude();
         QString sValue = QString::number(dValue,'f',4);
      
         m_Latitude = sValue;
         emit LatitudeChanged();
      }
      

      But the value on the screen is always "Longitude: --.----".

      The value in the BackEnd-Class m_Latitude is updated correctly.
      The value "backend.Latitude" has always "--.----".

      The base code of my QML Application is starting with the sample "wearable" Sample from here

      Where is my fault ?

      Best regards and thanks for any help
      R.

      E Offline
      E Offline
      Eeli K
      wrote on last edited by
      #2

      @Ritchie Show your main.cpp.

      1 Reply Last reply
      1
      • R Offline
        R Offline
        Ritchie
        wrote on last edited by
        #3

        Hi,

        here is the code of my main.cpp

        int main(int argc, char *argv[])
        {
        //QTranslator 				translator;
        int							Status=0;
        gpsread     *m_gps;
        
            QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
            QGuiApplication app(argc, argv);
        
            qmlRegisterType<BackEnd>("name.backend", 1, 0, "BackEnd");
        
            app.setOrganizationName(PROGRAM_NAME);
            QTextCodec::setCodecForLocale( QTextCodec::codecForName("UTF-8") );
            QLocale::setDefault(QLocale::German);											// TODO: Do it for all countrys
        
        
            QQuickStyle::setStyle(QStringLiteral("qrc:/qml/Style"));
        
            QQmlApplicationEngine engine;
            engine.load(QUrl(QStringLiteral("qrc:/carclient.qml")));
        
        	tzset(); 
        
            SensorBuffer = new 	SensorValueDatas();                                         // Create a Query Buffer
        
        	ApplicationPath=app.applicationDirPath () + "/";								// we are running on mac or linux
        
        	loadSystemSettings();
        
            m_ProgramisRunning=true;
        
            m_gps= new gpsread();
        
            DebugDiagnosis = new ProgrammDiagnosis(ApplicationPath);
            DebugDiagnosis->writelog(QObject::tr("carclient"),QObject::tr("Main"),QObject::tr("Info"),QObject::tr("Program startup"));
        
            QThread* Data_thread = new QThread;
            m_DataThread = new DataThread(&m_ProgramisRunning,SensorBuffer,DebugDiagnosis);	// Create a thread for reading the unit datablocks
            m_DataThread->moveToThread(Data_thread);
            QObject::connect(Data_thread, SIGNAL (started()), m_DataThread, SLOT (run()));
        
            QThread* Sensor_thread = new QThread;
            m_SensorThread = new SensorThread(&m_ProgramisRunning,SensorBuffer,DebugDiagnosis);	// Create a thread for reading the unit datablocks
            m_SensorThread->moveToThread(Sensor_thread);
            QObject::connect(Sensor_thread, SIGNAL (started()), m_SensorThread, SLOT (run()));
        
            Data_thread->start();                                  // Start the background tasks
            Sensor_thread->start();
        
            Status=app.exec();
            QThread::msleep(2000);														// Wait a little bit
            m_ProgramisRunning=false;
        
            SensorBuffer->clear();                                                     // clear the query Buffer
            delete  SensorBuffer;
            SensorBuffer=NULL;
        
            delete  m_SensorThread;
            delete  m_DataThread;
            delete  Data_thread;
            delete  Sensor_thread;
            delete	DebugDiagnosis;
            delete  m_gps;
        
        	return Status;
        }
        

        Best regards
        R.

        E 1 Reply Last reply
        0
        • GrecKoG Offline
          GrecKoG Offline
          GrecKo
          Qt Champions 2018
          wrote on last edited by
          #4

          @Ritchie said in How to update a text value from C++ dynamic ..:

          onTextChanged:
          {
          txtLatitude.text = qsTr("Longitude: ") + backend.Latitude
          }

          Why do you do this ?
          The previous txtLatitude.text: qsTr("Longitude: ") + backend.Latitude ought to be enough.
          You break the binding by affecting a value imperatively to text.

          1 Reply Last reply
          1
          • R Ritchie

            Hi,

            here is the code of my main.cpp

            int main(int argc, char *argv[])
            {
            //QTranslator 				translator;
            int							Status=0;
            gpsread     *m_gps;
            
                QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                QGuiApplication app(argc, argv);
            
                qmlRegisterType<BackEnd>("name.backend", 1, 0, "BackEnd");
            
                app.setOrganizationName(PROGRAM_NAME);
                QTextCodec::setCodecForLocale( QTextCodec::codecForName("UTF-8") );
                QLocale::setDefault(QLocale::German);											// TODO: Do it for all countrys
            
            
                QQuickStyle::setStyle(QStringLiteral("qrc:/qml/Style"));
            
                QQmlApplicationEngine engine;
                engine.load(QUrl(QStringLiteral("qrc:/carclient.qml")));
            
            	tzset(); 
            
                SensorBuffer = new 	SensorValueDatas();                                         // Create a Query Buffer
            
            	ApplicationPath=app.applicationDirPath () + "/";								// we are running on mac or linux
            
            	loadSystemSettings();
            
                m_ProgramisRunning=true;
            
                m_gps= new gpsread();
            
                DebugDiagnosis = new ProgrammDiagnosis(ApplicationPath);
                DebugDiagnosis->writelog(QObject::tr("carclient"),QObject::tr("Main"),QObject::tr("Info"),QObject::tr("Program startup"));
            
                QThread* Data_thread = new QThread;
                m_DataThread = new DataThread(&m_ProgramisRunning,SensorBuffer,DebugDiagnosis);	// Create a thread for reading the unit datablocks
                m_DataThread->moveToThread(Data_thread);
                QObject::connect(Data_thread, SIGNAL (started()), m_DataThread, SLOT (run()));
            
                QThread* Sensor_thread = new QThread;
                m_SensorThread = new SensorThread(&m_ProgramisRunning,SensorBuffer,DebugDiagnosis);	// Create a thread for reading the unit datablocks
                m_SensorThread->moveToThread(Sensor_thread);
                QObject::connect(Sensor_thread, SIGNAL (started()), m_SensorThread, SLOT (run()));
            
                Data_thread->start();                                  // Start the background tasks
                Sensor_thread->start();
            
                Status=app.exec();
                QThread::msleep(2000);														// Wait a little bit
                m_ProgramisRunning=false;
            
                SensorBuffer->clear();                                                     // clear the query Buffer
                delete  SensorBuffer;
                SensorBuffer=NULL;
            
                delete  m_SensorThread;
                delete  m_DataThread;
                delete  Data_thread;
                delete  Sensor_thread;
                delete	DebugDiagnosis;
                delete  m_gps;
            
            	return Status;
            }
            

            Best regards
            R.

            E Offline
            E Offline
            Eeli K
            wrote on last edited by
            #5

            @Ritchie You made a classic and common mistake: you register the type which you don't need to do, nor do you need to import it. Instead you should create an object in C++ and use setContextProperty. Example taken from the docs:

            QQmlEngine engine;
             QStringListModel modelData;
             QQmlContext *context = new QQmlContext(engine.rootContext());
             context->setContextProperty("myModel", &modelData);
            

            Then the object is available in QML as a global object.

            1 Reply Last reply
            0
            • R Offline
              R Offline
              Ritchie
              wrote on last edited by
              #6

              @GrecKo

              Why do you do this ?
              The previous txtLatitude.text: qsTr("Longitude: ") + backend.Latitude ought to be enough.
              You break the binding by affecting a value imperatively to text.
              I thought this needed to update the Text information, when the "function emit LatitudeChanged();"
              will update the text information.
              Its this not needed ?

              @Eeli K
              I will take a closer look into it. Have to find out the correct meaning of these function.
              Totally new for me.

              E 1 Reply Last reply
              0
              • R Ritchie

                @GrecKo

                Why do you do this ?
                The previous txtLatitude.text: qsTr("Longitude: ") + backend.Latitude ought to be enough.
                You break the binding by affecting a value imperatively to text.
                I thought this needed to update the Text information, when the "function emit LatitudeChanged();"
                will update the text information.
                Its this not needed ?

                @Eeli K
                I will take a closer look into it. Have to find out the correct meaning of these function.
                Totally new for me.

                E Offline
                E Offline
                Eeli K
                wrote on last edited by
                #7

                @Ritchie You have:

                text: qsTr("Longitude: ") + backend.Latitude //sic! should be "Latitude"?
                

                If backend.Latitude is Q_PROPERTY and the change signal is emitted in C++ the 'text' property is updated automatically. That's the idea of property bindings in QML - you don't have to do it imperatively in javascript code.

                1 Reply Last reply
                0
                • R Offline
                  R Offline
                  Ritchie
                  wrote on last edited by
                  #8

                  @Eeli-K
                  You are right. I changed it to

                  Text {
                           id: txtLatitude
                           anchors.horizontalCenter: parent.horizontalCenter
                          text: qsTr("Latitude: ") + BackEnd.Latitude
                          font.pixelSize: UIStyle.fontSizeS
                          font.italic: true
                          color: UIStyle.colorQtGray3
                          }
                  

                  I also add these line into the main function

                  BackEnd     UserDisplay;
                  ...
                  ...
                  QQmlEngine  QMLEngine;
                  QQmlContext *context = new QQmlContext(QMLEngine.rootContext());
                  context->setContextProperty("BackEnd", &UserDisplay);
                  

                  But now I get an Compiler error for the last two lines.

                  Main.cpp:95: Fehler: invalid use of incomplete type ‘class QQmlContext’      QQmlContext *context = new QQmlContext(QMLEngine.rootContext());
                     
                  

                  and

                  invalid use of incomplete type ‘class QQmlContext’      context->setContextProperty("BackEnd", &UserDisplay);
                  

                  But all the sample I saw in the Internet are using these two line.

                  Best regards
                  R.

                  E 1 Reply Last reply
                  1
                  • R Ritchie

                    @Eeli-K
                    You are right. I changed it to

                    Text {
                             id: txtLatitude
                             anchors.horizontalCenter: parent.horizontalCenter
                            text: qsTr("Latitude: ") + BackEnd.Latitude
                            font.pixelSize: UIStyle.fontSizeS
                            font.italic: true
                            color: UIStyle.colorQtGray3
                            }
                    

                    I also add these line into the main function

                    BackEnd     UserDisplay;
                    ...
                    ...
                    QQmlEngine  QMLEngine;
                    QQmlContext *context = new QQmlContext(QMLEngine.rootContext());
                    context->setContextProperty("BackEnd", &UserDisplay);
                    

                    But now I get an Compiler error for the last two lines.

                    Main.cpp:95: Fehler: invalid use of incomplete type ‘class QQmlContext’      QQmlContext *context = new QQmlContext(QMLEngine.rootContext());
                       
                    

                    and

                    invalid use of incomplete type ‘class QQmlContext’      context->setContextProperty("BackEnd", &UserDisplay);
                    

                    But all the sample I saw in the Internet are using these two line.

                    Best regards
                    R.

                    E Offline
                    E Offline
                    Eeli K
                    wrote on last edited by
                    #9

                    @Ritchie You have to include it in normal C++ way: #include <QQmlContext>

                    1 Reply Last reply
                    0
                    • R Offline
                      R Offline
                      Ritchie
                      wrote on last edited by
                      #10

                      @Eeli-K
                      You are right. That was the missing line.

                      But now I get

                      qrc:/qml/GPS/GPSPage.qml:88: ReferenceError: BackEnd is not defined
                      
                      

                      Which is this line:

                         text: qsTr("Latitude: ") + BackEnd.Latitude
                      
                      E 1 Reply Last reply
                      0
                      • R Ritchie

                        @Eeli-K
                        You are right. That was the missing line.

                        But now I get

                        qrc:/qml/GPS/GPSPage.qml:88: ReferenceError: BackEnd is not defined
                        
                        

                        Which is this line:

                           text: qsTr("Latitude: ") + BackEnd.Latitude
                        
                        E Offline
                        E Offline
                        Eeli K
                        wrote on last edited by Eeli K
                        #11

                        @Ritchie I don't know if this is the reason but QML expects type names to begin with uppercase and property names etc. to begin with lowercase. So try

                        context->setContextProperty("backend", &UserDisplay);
                        

                        and backend.Latitude etc. in QML.

                        I recommend also sticking to Qt coding convention with C++ upper/lowercase: class names begin with upper case, property, function and object names begin with lowercase. It shouldn't be necessary, I think, but may save you or someone else from some headache when reading the code.

                        1 Reply Last reply
                        0
                        • GrecKoG Offline
                          GrecKoG Offline
                          GrecKo
                          Qt Champions 2018
                          wrote on last edited by
                          #12

                          @Ritchie said in How to update a text value from C++ dynamic ..:

                          QQmlContext *context = new QQmlContext(QMLEngine.rootContext());

                          This is a reason. You are constructing a child context that no object has access to and you add your property into it.

                          Just add it to the rootContext of the engine you created in your main and where you loaded your qml file.
                          Additionally, you should set the context property before loading the qml file.

                          1 Reply Last reply
                          0
                          • R Offline
                            R Offline
                            Ritchie
                            wrote on last edited by
                            #13

                            @GrecKo
                            Thanks. Thats was the reason:

                                QQmlApplicationEngine engine;
                                engine.rootContext()->setContextProperty("BackEnd", &UserDisplay);
                                engine.load(QUrl(QStringLiteral("qrc:/carclient.qml")));
                            

                            Best regards
                            R.

                            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