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. Connecting C++ with QML

Connecting C++ with QML

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
25 Posts 9 Posters 528 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.
  • G Offline
    G Offline
    Groundbounce
    wrote last edited by
    #1

    I am at the end of my tether, I have spent weeks trying to understand this. Please don't tell me about your fantastic documentation, that is not the answer for a novice and putting data on a screen controlled by Qt Quik that is computed in C++ is really a fundamental requirement!

    The manuals talk about several ways at once, refer to themselves in a circles and don't explain from start to finish. Tutorials are just a waste of time as every one does not explain the theory behind "do this, now do this, now do this, voila" the problem is that the examples used to show the functionality start out by setting up something else rather complex of which the object of the tutorial is now such a small part the point is lost.

    All I want to do is prove that I can put data that I have in C++ onto a screen. It looks like singletons may be the way but then there are loads of recommendations against. Basically anything that looks like it will be too the point and easy to implement is not recommended, everything else is not really explained.

    C 1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote last edited by
      #2

      Hi,

      What kind of data are you trying to show in QtQuick that you have in C++ ?
      How is it structured ?
      How do you want to show it ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • G Offline
        G Offline
        Groundbounce
        wrote last edited by
        #3

        At the moment I am just trying to understand the principle, I'd feel like I got to the top of Everest just to stick an integer on an otherwise empty window (that was stored in a live C++ variable of course).

        I need to receive data over a serial bus that will be displayed on the screen. I'm not sure how I will structure it but there will not be much.

        I'm coming to the conclusion the way it was intended to be done was via a server connection.

        1 Reply Last reply
        0
        • G Groundbounce

          I am at the end of my tether, I have spent weeks trying to understand this. Please don't tell me about your fantastic documentation, that is not the answer for a novice and putting data on a screen controlled by Qt Quik that is computed in C++ is really a fundamental requirement!

          The manuals talk about several ways at once, refer to themselves in a circles and don't explain from start to finish. Tutorials are just a waste of time as every one does not explain the theory behind "do this, now do this, now do this, voila" the problem is that the examples used to show the functionality start out by setting up something else rather complex of which the object of the tutorial is now such a small part the point is lost.

          All I want to do is prove that I can put data that I have in C++ onto a screen. It looks like singletons may be the way but then there are loads of recommendations against. Basically anything that looks like it will be too the point and easy to implement is not recommended, everything else is not really explained.

          C Offline
          C Offline
          CassD
          wrote last edited by
          #4

          @Groundbounce said in Connecting C++ with QML:

          I am at the end of my tether, I have spent weeks trying to understand this. Please don't tell me about your fantastic documentation, that is not the answer for a novice and putting data on a screen controlled by Qt Quik that is computed in C++ is really a fundamental requirement!

          That's exactly what tutorials are made for. Making a little search on youtube would have got you a few interesting results like the Vid n°47 in the playlist
          You should also find a few interesting videos from MontyTheSoftwareEngineer (he's the only name I can currently remember of, I don't think much misspelling his name) but there are lots of others.

          1 Reply Last reply
          0
          • G Offline
            G Offline
            Groundbounce
            wrote last edited by
            #5

            You think I have not been looking? I'll watch those tomorrow as it's late now.

            So far connecting C++ and QML tutorials always turn out to be creating a class in C++ with the object instantiated in QML and used exclusively in QML, this is not what I am looking for. Much of the material is out of date and will throw compiler errors and warnings, because the reasons for things are not explained I have nothing to go on. Indeed I am convinced the only fool proof way to do it is via a server! But that is another skill i will have to master! so close, yet so far away.

            This little gem from here: https://doc.qt.io/qt-6/qtqml-cppintegration-interactqmlfromcpp.html#connecting-to-qml-signals just throws errors, I am not even sure where the code is supposed to go:

            // Using QQmlComponent
            QQmlEngine engine;
            QQmlComponent component(&engine,
            QUrl::fromLocalFile("MyItem.qml"));
            QObject *object = component.create();
            ...
            delete object;

            jsulmJ C 2 Replies Last reply
            0
            • G Groundbounce

              You think I have not been looking? I'll watch those tomorrow as it's late now.

              So far connecting C++ and QML tutorials always turn out to be creating a class in C++ with the object instantiated in QML and used exclusively in QML, this is not what I am looking for. Much of the material is out of date and will throw compiler errors and warnings, because the reasons for things are not explained I have nothing to go on. Indeed I am convinced the only fool proof way to do it is via a server! But that is another skill i will have to master! so close, yet so far away.

              This little gem from here: https://doc.qt.io/qt-6/qtqml-cppintegration-interactqmlfromcpp.html#connecting-to-qml-signals just throws errors, I am not even sure where the code is supposed to go:

              // Using QQmlComponent
              QQmlEngine engine;
              QQmlComponent component(&engine,
              QUrl::fromLocalFile("MyItem.qml"));
              QObject *object = component.create();
              ...
              delete object;

              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote last edited by
              #6

              @Groundbounce said in Connecting C++ with QML:

              I am not even sure where the code is supposed to go

              In main() for example. Or where ever you want to handle this in your application.
              "just throws errors" - mentioning the actual errors would help others to help you. This piece of code is not a complete example, just something to illustrate how to use QQmlComponent.

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • G Offline
                G Offline
                Groundbounce
                wrote last edited by
                #7

                Every project starts with the following in main:

                QQmlApplicationEngine engine;
                    QObject::connect(
                        &engine,
                        &QQmlApplicationEngine::objectCreationFailed,
                        &app,
                        []() { QCoreApplication::exit(-1); },
                        Qt::QueuedConnection);
                    engine.loadFromModule("kdab-n46", "Main");
                

                in the video series linked to in video number 46 this is all missing. The sorts of errors I got were along the lines of declaring another engine because of the line:

                QQmlEngine engine;
                

                Without being an expert on this system yet I can see that 2 "engines" are being created, but I'm not going to go taking out code that was autogenerated.

                1 Reply Last reply
                0
                • J.HilkJ Offline
                  J.HilkJ Offline
                  J.Hilk
                  Moderators
                  wrote last edited by J.Hilk
                  #8

                  @Groundbounce

                  There are a couple of ways to get data from c++ to QML and vice versa.

                  None are wrong, some leave a bitter after taste for some but thats, in the end, a personal issue.

                  In some cases, for example if you want to do some math equations, take the input from qml intafce and show the result back in qml. This is a case where I would suggest creating a c++ class that is instanciated in QML and destroyed by it. No reason to manage an instance of that class in your c++ part of the application.

                  In your case, you probably have a sophisticated c++ application that is managing the serial bus communication and data management and you only want to expose and access that data in QML

                  You could do that via Singleton's or via a setContextProperty

                  Either way, your c++ class should have QPROPERTY() defined qmlname,getters, setters and notify signals that wha you can simply access the property via the qmlname and Qt does the correct calls the the defined setters and getters

                  here's an example:

                  #include <QGuiApplication>
                  #include <QQmlApplicationEngine>
                  #include <QQmlContext>
                  #include <QObject>
                  #include <QString>
                  #include <QDebug>
                  
                  class MyData : public QObject {
                      Q_OBJECT
                      Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
                  public:
                      explicit MyData(QObject *parent = nullptr) : QObject(parent), m_text("Hello from C++") {}
                  
                      QString text() const { return m_text; }
                  
                      void setText(const QString &newText) {
                          if (m_text != newText) {
                              m_text = newText;
                              emit textChanged();
                          }
                          qDebug() << Q_FUNC_INFO << newText;
                      }
                  
                  signals:
                      void textChanged();
                  
                  private:
                      QString m_text;
                  };
                  
                  int main(int argc, char *argv[]) {
                      QGuiApplication app(argc, argv);
                  
                      MyData myData;
                  
                      QQmlApplicationEngine engine;
                      engine.rootContext()->setContextProperty("myData", &myData);
                  
                      const char *qmlCode = R"(
                          import QtQuick 2.15
                          import QtQuick.Window 2.15
                          import QtQuick.Controls 2.15
                  
                          Window {
                              visible: true
                              width: 400
                              height: 200
                              title: "C++ to QML Example"
                  
                              Column {
                                  anchors.centerIn: parent
                                  spacing: 10
                  
                                  Text {
                                      text: myData.text
                                      font.pointSize: 16
                                  }
                  
                                  TextField {
                                      id: inputField
                                      width: 200
                                      placeholderText: "Enter new text"
                                      onTextChanged: myData.text = text
                                  }
                              }
                          }
                      )";
                  
                      engine.loadData(qmlCode);
                  
                      if (engine.rootObjects().isEmpty())
                          return -1;
                  
                      return app.exec();
                  }
                  
                  #include "main.moc"
                  
                  

                  this is all in main.cpp no need for anything else


                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  1 Reply Last reply
                  2
                  • G Offline
                    G Offline
                    Groundbounce
                    wrote last edited by Groundbounce
                    #9

                    OK, so this works, again none of the standard setup that I usually see in main.cpp when I start a new project.

                    The IDE reports that main.moc cannot be found but it still compiles and then stops complaining.
                    But it runs,

                    Of course trying to move the QML stuff into the Main.qml file is not working.

                    J.HilkJ 1 Reply Last reply
                    0
                    • G Groundbounce

                      OK, so this works, again none of the standard setup that I usually see in main.cpp when I start a new project.

                      The IDE reports that main.moc cannot be found but it still compiles and then stops complaining.
                      But it runs,

                      Of course trying to move the QML stuff into the Main.qml file is not working.

                      J.HilkJ Offline
                      J.HilkJ Offline
                      J.Hilk
                      Moderators
                      wrote last edited by
                      #10

                      @Groundbounce *.moc files are generated by the meta(m)object(o)compiler(c), needed for Qt-magic. You're not supposed to use the Q_OBJECT macro inside cpp files. The automatic setup doesn't work then, so you end up needing to include the moc file manually


                      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                      Q: What's that?
                      A: It's blue light.
                      Q: What does it do?
                      A: It turns blue.

                      1 Reply Last reply
                      0
                      • G Offline
                        G Offline
                        Groundbounce
                        wrote last edited by
                        #11

                        Right so now have it working with the class in a header file of it's own and the QML stuff in Main.qml,
                        Thank you!
                        Next I'll try and put the QML stuff in a file of it's own.

                        1 Reply Last reply
                        0
                        • G Groundbounce

                          You think I have not been looking? I'll watch those tomorrow as it's late now.

                          So far connecting C++ and QML tutorials always turn out to be creating a class in C++ with the object instantiated in QML and used exclusively in QML, this is not what I am looking for. Much of the material is out of date and will throw compiler errors and warnings, because the reasons for things are not explained I have nothing to go on. Indeed I am convinced the only fool proof way to do it is via a server! But that is another skill i will have to master! so close, yet so far away.

                          This little gem from here: https://doc.qt.io/qt-6/qtqml-cppintegration-interactqmlfromcpp.html#connecting-to-qml-signals just throws errors, I am not even sure where the code is supposed to go:

                          // Using QQmlComponent
                          QQmlEngine engine;
                          QQmlComponent component(&engine,
                          QUrl::fromLocalFile("MyItem.qml"));
                          QObject *object = component.create();
                          ...
                          delete object;

                          C Offline
                          C Offline
                          CassD
                          wrote last edited by
                          #12

                          @Groundbounce said in Connecting C++ with QML:

                          So far connecting C++ and QML tutorials always turn out to be creating a class in C++ with the object instantiated in QML and used exclusively in QML, this is not what I am looking for

                          That's curious, most of those tutorials instanciate those classes in C++ and pass it to QML via (as JHilk already suggested)
                          engine->rootContext()->setContextProperty ( ... )
                          as the easiest is to instanciate in C++ and pass it to QML. Creating a qml module for a component to be instanciatable in QML is a little more tricky ;) ;) ;)

                          1 Reply Last reply
                          0
                          • G Offline
                            G Offline
                            Groundbounce
                            wrote last edited by
                            #13

                            Try https://academy.qt.io/enrollments/254032569/details

                            This has no C++ code in it at all except creating the actual class, it simply takes a mouse input and changes something on the screen, the class is instantiated in the QML file.

                            This is the sort of thing the manual talks about a lot.

                            again this video from the playlist linked above is very vague on actual detail: https://www.youtube.com/watch?v=quFciLDIxUw&list=PL6CJYn40gN6hdNC1IGQZfVI707dh9DPRc&index=46

                            1 Reply Last reply
                            0
                            • C Offline
                              C Offline
                              CassD
                              wrote last edited by
                              #14

                              I've recommended that playlist multiple times and everyone so far has been capable to work with. So why not you ?

                              1 Reply Last reply
                              0
                              • G Offline
                                G Offline
                                Groundbounce
                                wrote last edited by
                                #15

                                I don't know. I don't know what I don't know. My programming background is microcontrollers. This is my fist experimenting with programming on an operating system and it is as I expected very different.

                                It almost looks like he set up the variables within the setContextProperty - this is video 46 - I don't see at any point the actual C++ variable he is linking to. in fact I would say those are constants. The he talks about gadgets.

                                The code that @J.Hilk posted gets it in one does exactly what every newcommer to QML will be asking, how do I get variables in C++ into QML. I get that someone has this dream of QML stuff being practically a separate program from the C++ back end but they must communicate somehow.

                                As I said the only way to do this without doing anything that upsets anyone in terms of total reusability is to totally separate the two (automatic multithreading done right there) into two programs and have them communicate via something that we know both speak like a webserver or database (I have no abilities in either yet).

                                The way QML is presented feels like someone wants to one day have just QML, no C++. I have an entire book on QML, but the author explicitly said that he would not even talk about how QML and C++ share data as the book is about QML only. Well as Jesper said in video 46, without C++ QML programs are just toys.

                                1 Reply Last reply
                                0
                                • C Offline
                                  C Offline
                                  CassD
                                  wrote last edited by
                                  #16

                                  Qt is not all about QML for sure and C++ still has a huge importance in it, apps are not just about user interface, there's lots of core stuff behind that the author was probably not focusing about. Yeah just like toys like Jesper said. You still need a lots of C++ for communication, data handling and so on.

                                  The author of your book probably just wanted to focus on the QML language itself, I don't know the reasons about that, but I guess he just wanted to focus on UI creation only and forgetting all the core stuff and how to integrate core with QML ? Does he explain the reasons of the choice when he makes the statement ?
                                  I just guess this might a book just about UI creation, not that much intened for developpers.

                                  1 Reply Last reply
                                  0
                                  • G Offline
                                    G Offline
                                    Groundbounce
                                    wrote last edited by
                                    #17

                                    The book is just about QML: Qt6 QML for beginners by Daniel Gakwaya. Very good for QML yes, I recommend it. But someone has to explain how to do this, he came so close with QML functionality but said he would not touch on the C++ side of it.

                                    1 Reply Last reply
                                    0
                                    • Z Offline
                                      Z Offline
                                      zvoopz
                                      wrote last edited by
                                      #18

                                      The most simple way to use QML is treat it as user interface only. All calculations, validations and logic makes cpp. My QML is dumb: it sends input and receives output to show. I am migrating from Qt Widget to QML now and can share my experience.
                                      The most difficult part for me was to find an approach to provide communications between these two parts of app and register their binding. I have made a controller cpp class which manages requests and sends data from backend cpp classes and UI through Qt signal-slot mechanism. No Q_PROPERTY in my app just signals. Any communication between any calculator class and UI goes through controller. Controller owns calculators and makes all decisions.

                                      Controller.h
                                      class Controller : public QObject
                                      {
                                          Q_OBJECT
                                          QML_SINGLETON
                                          QML_ELEMENT
                                      public:
                                          explicit Controller(QObject *parent = nullptr);
                                      //next is a set of functions which are triggered by QML, Q_INVOKABLE is a keyword that connects
                                          Q_INVOKABLE void goToMainWindow();
                                          Q_INVOKABLE void loadWindow(const QString &qmlFileName, const QString &key);
                                          Q_INVOKABLE void window1TextFieldsParser();
                                          Q_INVOKABLE void window2TextFieldsParser();
                                          Q_INVOKABLE void window3TextFieldsParser();
                                          Q_INVOKABLE void profileEditTextFieldsParser();
                                          Q_INVOKABLE void on_loadProfileButton_clicked(const QString &nameOfProfile);
                                      //I extract and send only strings, cpp decides how to treat them
                                      
                                      signals: //To QML
                                          void window1Changed(QString summary);
                                          void showInfo(const QString &message, const QString &title, QObject* window);
                                          void showConfirmationDialog(const QString &message, const QString &title, QObject* window, const QString &requestId);
                                          void window2Changed(const QString summary);
                                          void clearListViewItems();
                                          void addItemsToListView (const QString &profileName);
                                          void updateLabel(const QString &summary);   
                                      

                                      How QML sends signal?

                                      Button{
                                              id: button      
                                              }
                                              //LOGIC
                                              onClicked: {
                                      	//QML emits signal to Controller  that switches window
                                              Controller.loadWindow("Window2.qml", "Window2")
                                              }
                                          }
                                      
                                      Button{
                                          id: loadProfileButton
                                          text: qsTr("Load")
                                           onClicked:{
                                       	//LOGIC
                                              if(profileListView.currentIndex!==-1){
                                      		//assign variable 
                                                     let selectedProfileName = model.get(profileListView.currentIndex).name
                                                     //and emit signal with value
                                                     Controller.on_loadProfilePushButton_clicked(selectedProfileName)
                                             }else{
                                      		//show error message
                                                      messenger.showInfo(qsTr("Select a profile"), qsTr("Error"))
                                             }
                                       }
                                      

                                      How QML receives signal?

                                      Connections {
                                            target: Controller
                                           function onClearListViewItems() {
                                           model.clear()
                                           }
                                      
                                               function onAddItemsToListView(profileName) {
                                               model.append({ name: profileName })
                                               }
                                         }
                                      

                                      Easy but very verbose language

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

                                        Why even do it in c++ if all your data is stored in QML and you are not using properties or models in c++?

                                        Given the name of the invokables and slots it seems that the c++ is too coupled to the QML and it goes against what is usually recommended.

                                        1 Reply Last reply
                                        0
                                        • Z Offline
                                          Z Offline
                                          zvoopz
                                          wrote last edited by
                                          #20

                                          Because this is my first experience in QML and I never used JavaScript as well to write additional code in QML but I feel confident in c++.
                                          I have two dozens of TextField objects to accept user input in different ways with input validation. It might be string, integer or double that`s why I use the most simple approach for my current level of knowledge.

                                          I have a window with 7 TextFields and single Input button. How do I parse them?

                                          //QML
                                          Button{
                                                 id: inputWindow1Button
                                                 objectName: "inputWindow1Button"
                                                 text: qsTr("Input")
                                          	//LOGIC
                                                  onClicked: { //emits signal to run Controller::window1TextFieldsParser() which is declared as Q_INVOKABLE
                                                     Controller.window1TextFieldsParser()
                                                }
                                          }
                                          

                                          .cpp

                                          void Controller::window1TextFieldsParser(){
                                            QQuickWindow* multiWindow = m_currentWindow; //currently active window where cpp looks for 
                                            objectName to parse
                                            QObject* speed = multiWindow->findChild<QObject*>("speed1of3"); //look for QML objectName
                                            QString speedText = speed->property("text").toString().trimmed(); //extract text from "speed1of3" TextField 
                                            QML object
                                            double speedCheck;
                                          
                                          if (speedText.isEmpty()){//check if QString is empty
                                            //Error signal to QML
                                            emit showInfo(tr("Speed field is empty"),
                                                        tr("Invalid input"), m_currentWindow);
                                            return;
                                          }else{
                                            //convert  QString to double, normalize input (treat both coma and dot as decimal separator)
                                            speedCheck = convertStringToDouble(speedText); 
                                          }
                                            //validate input range
                                          if(speedCheck<=0 || std::isnan(speedCheck)){
                                             //handle invalid input through emit showInfo()
                                            return;
                                          }else{
                                            m_speed=speedCheck; //assign member variable with valid value
                                          }
                                          }
                                          
                                          Ronel_qtmasterR 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