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. Change QML Screen from C++ thread
Forum Updated to NodeBB v4.3 + New Features

Change QML Screen from C++ thread

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
8 Posts 3 Posters 656 Views 3 Watching
  • 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.
  • J Offline
    J Offline
    JaviRodriguez
    wrote on last edited by
    #1

    Hello,
    My project consist in a simple touchscreen that enables few switchs by touching a button in the screen. When the application starts, runs in parallel a thread to launch a TCP socket (CreateSocket) and keeps listening for incoming connections.
    When an external connection is linked I would like to show the same screen that is shown when you click on "Advanced" button (Advanced.qml).

    I red the following tutorials but I dont know how to define the signals/slots. How should I define the signals to activate the screen that I in local mode activate by clicking on the button "Advanced"
    http://doc.qt.io/qt-4.8/qtbinding.html
    https://wiki.qt.io/Receiving_signals_with_arguments_in_QML_from_C%2B%2B

    Can anybody help me? I would really aprreciate it! I am quite new by Qt!

    dataprovider.h

    Class DataProvider : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)
        public:
           explicit DataProvider(QObject *parent = 0);
    
    void setValue(int newVal) {    // <--- do your stuff to update the value
    
        if (newVal != m_value) {
            m_value = newVal;
          //  qDebug() << "changing to" << newVal;
            emit valueChanged(newVal);     // <--- emit signal to notify QML!
        }
    }
    int value() const {
        return m_value;
    }
     Q_INVOKABLE void on(int position);
     Q_INVOKABLE void adv_on(int switch_id, int position, bool is_off);
    
     void* CreateSocket(DataProvider *dataP);
    
    signals:
        void valueChanged(int i);             // <--- actual signal used as notification in Q_PROPERTY
    
    private:
        int m_value;     // <--- member value which stores the actual value
    

    };

    main.cpp

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication app(argc, argv);
    QQmlApplicationEngine engine; /*Every app needs an app engine*/
    
    DataProvider dt;              /*Class with properties to access from back-end to front-end*/
    engine.rootContext() -> setContextProperty("dataProvider", &dt);
    engine.addImportPath(":/imports");
    
    std::thread thread(&CreateSocket, &dt);
    
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    return app.exec();
    

    mainwindow.qml

    import QtQuick.Extras 1.4
    import QtQuick.Dialogs 1.2
    
    Rectangle {
        id: root
        visible: true
        width: 800
        height: 480
    }
      // Extra objects removed to be irrelevant
    Advanced {
        id: advanced
        anchors.left: parent.left
        anchors.leftMargin: 450
        anchors.top: parent.top
        anchors.topMargin: 408
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 26
        anchors.right: parent.right
        anchors.rightMargin: 277
    }
    

    Advanced.qml

    import QtQuick 2.4
    Item {
        id: advance
        width: 74
        height: 50
    
    Image {
        id: logo
        width: 74
        height: 50
        fillMode: Image.PreserveAspectFit
        source: "images/Next.png"
    
        MouseArea {
            anchors.bottomMargin: 0
            anchors.topMargin: 0
            anchors.leftMargin: 0
            anchors.rightMargin: 0
            anchors.fill: parent
            onClicked: {
                   pageLoader.source = "AdvancedPage.qml";
                       }
                 }
            }
    }
    
    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      How should I define the signals to activate the screen that I in local mode activate by clicking on the button "Advanced"

      Can you rephrase this? I have no idea what you mean.

      In any case, you attach your DataProvider correctly. It is now available as dataProvider in your whole QML application. So whenever you want to use it, you can simply call it, like:

      Button {
        onClicked: dataProvider.value = 1234
      }
      

      (Z(:^

      1 Reply Last reply
      0
      • J Offline
        J Offline
        JaviRodriguez
        wrote on last edited by
        #3

        Hi sierdzio, thanks for your answer.

        I try to explain it better:
        The project consists on a switch driver with "local" and "remote" working modes.
        In local mode you push few QML buttons that call C++ funtions ("on" and "adv_on") to activate GPIO outputs of a Raspberry Pi.
        To work in remote mode, a TCP socket is running in a separate thread and listen for incoming connections. These remote clients send commands corresponding to button pressings in local mode, therefore I use the same C++ functions ("on" and "adv_on").

        Until now (local mode) I call C++ functions from QML (when I push the button with the mouse).
        What I want to do now (remote mode) is to interact QML objects from the TCP socket written in C++ code .

        I would like to activate the QML button "Advance" from the C++ socket, as it would have been pressed with the mouse.

        I hope to have explained better now.

        Thanks for your support.

        Pablo J. RoginaP 1 Reply Last reply
        0
        • J JaviRodriguez

          Hi sierdzio, thanks for your answer.

          I try to explain it better:
          The project consists on a switch driver with "local" and "remote" working modes.
          In local mode you push few QML buttons that call C++ funtions ("on" and "adv_on") to activate GPIO outputs of a Raspberry Pi.
          To work in remote mode, a TCP socket is running in a separate thread and listen for incoming connections. These remote clients send commands corresponding to button pressings in local mode, therefore I use the same C++ functions ("on" and "adv_on").

          Until now (local mode) I call C++ functions from QML (when I push the button with the mouse).
          What I want to do now (remote mode) is to interact QML objects from the TCP socket written in C++ code .

          I would like to activate the QML button "Advance" from the C++ socket, as it would have been pressed with the mouse.

          I hope to have explained better now.

          Thanks for your support.

          Pablo J. RoginaP Offline
          Pablo J. RoginaP Offline
          Pablo J. Rogina
          wrote on last edited by
          #4

          @JaviRodriguez Have you already check the QML / C++ integration documentation?

          So following the example of userNameChanged()/onUserNameChanged from that article, I'd suggest that your C++ backend handling the remote connection and parsing the commands, emit a signal (i.e. remoteModeRequested) whenever you know a remote connection has requested remote mode, so the QML handler onRemoteModeRequested will load/show the proper QML view for remote mode.

          Upvote the answer(s) that helped you solve the issue
          Use "Topic Tools" button to mark your post as Solved
          Add screenshots via postimage.org
          Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

          1 Reply Last reply
          0
          • J Offline
            J Offline
            JaviRodriguez
            wrote on last edited by
            #5

            @Pablo-J-Rogina
            Thank you for you answer. I red integration documentation you mention several times.
            This is exactly the point where I am stuck on: I emit the Signal but i do not how to Connect It to the "Advanced.qml" nor to activate the command 'pageLoader.source = "AdvancedPage.qml";' to load the wished qml Page.

            Could you please write a small example for me bases on muy code? I would really appreciate it.

            Thanks for your support.

            Pablo J. RoginaP 1 Reply Last reply
            0
            • J JaviRodriguez

              @Pablo-J-Rogina
              Thank you for you answer. I red integration documentation you mention several times.
              This is exactly the point where I am stuck on: I emit the Signal but i do not how to Connect It to the "Advanced.qml" nor to activate the command 'pageLoader.source = "AdvancedPage.qml";' to load the wished qml Page.

              Could you please write a small example for me bases on muy code? I would really appreciate it.

              Thanks for your support.

              Pablo J. RoginaP Offline
              Pablo J. RoginaP Offline
              Pablo J. Rogina
              wrote on last edited by
              #6

              @JaviRodriguez said in Change QML Screen from C++ thread:

              I emit the Signal but i do not how to Connect It to the "Advanced.qml"

              Could you show your QML code so far? (at least the part relevant to the signal handler)

              Upvote the answer(s) that helped you solve the issue
              Use "Topic Tools" button to mark your post as Solved
              Add screenshots via postimage.org
              Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

              J 1 Reply Last reply
              0
              • Pablo J. RoginaP Pablo J. Rogina

                @JaviRodriguez said in Change QML Screen from C++ thread:

                I emit the Signal but i do not how to Connect It to the "Advanced.qml"

                Could you show your QML code so far? (at least the part relevant to the signal handler)

                J Offline
                J Offline
                JaviRodriguez
                wrote on last edited by
                #7

                @Pablo-J-Rogina
                Hi. Following I show some relevant code.

                main.cpp

                 // I launch a new thread to run the socket
                 DataProvider dt;        /*Class with properties to access from back-end to front-end*/
                 std::thread thread(&CreateSocket, &dt);
                

                dataprovider.cpp

                 void* CreateSocket(DataProvider *dataP){
                  //... some irrelevant code
                 new_socket = accept(serverSocket, (struct sockaddr *)&serverAddr, (socklen_t*)&addr_size);
                         if (new_socket > 0)
                         {
                             emit dataP->RemoteModeOn();             
                         }}
                

                dataprovider.h

                class DataProvider : public QObject
                {
                Q_OBJECT
                signals:
                void RemoteModeOn (void);
                 }
                

                What I want is to call "AdvancedPage.qml" object in the same way that is done by "Advanced.qml" when I click with the mouse. I dont know how to tell the function RemoteModeOn to activate onClicked property of advanced.qml

                advanced.qml

                import QtQuick 2.4
                Item {
                  id: advance
                width: 74
                height: 50
                Image {
                    id: logo
                    width: 74
                    height: 50
                    fillMode: Image.PreserveAspectFit
                    source: {"images/Next.png"
                    dataProvider.QRemoteModeOn}
                
                    MouseArea {
                        anchors.bottomMargin: 0
                        anchors.topMargin: 0
                        anchors.leftMargin: 0
                        anchors.rightMargin: 0
                        anchors.fill: parent
                        onClicked: {
                               pageLoader.source = "AdvancedPage.qml";
                        }
                    }
                }
                }
                

                I hope this extract of code is enough to understand what I am trying to do.
                Thank you very much for your support.

                Pablo J. RoginaP 1 Reply Last reply
                0
                • J JaviRodriguez

                  @Pablo-J-Rogina
                  Hi. Following I show some relevant code.

                  main.cpp

                   // I launch a new thread to run the socket
                   DataProvider dt;        /*Class with properties to access from back-end to front-end*/
                   std::thread thread(&CreateSocket, &dt);
                  

                  dataprovider.cpp

                   void* CreateSocket(DataProvider *dataP){
                    //... some irrelevant code
                   new_socket = accept(serverSocket, (struct sockaddr *)&serverAddr, (socklen_t*)&addr_size);
                           if (new_socket > 0)
                           {
                               emit dataP->RemoteModeOn();             
                           }}
                  

                  dataprovider.h

                  class DataProvider : public QObject
                  {
                  Q_OBJECT
                  signals:
                  void RemoteModeOn (void);
                   }
                  

                  What I want is to call "AdvancedPage.qml" object in the same way that is done by "Advanced.qml" when I click with the mouse. I dont know how to tell the function RemoteModeOn to activate onClicked property of advanced.qml

                  advanced.qml

                  import QtQuick 2.4
                  Item {
                    id: advance
                  width: 74
                  height: 50
                  Image {
                      id: logo
                      width: 74
                      height: 50
                      fillMode: Image.PreserveAspectFit
                      source: {"images/Next.png"
                      dataProvider.QRemoteModeOn}
                  
                      MouseArea {
                          anchors.bottomMargin: 0
                          anchors.topMargin: 0
                          anchors.leftMargin: 0
                          anchors.rightMargin: 0
                          anchors.fill: parent
                          onClicked: {
                                 pageLoader.source = "AdvancedPage.qml";
                          }
                      }
                  }
                  }
                  

                  I hope this extract of code is enough to understand what I am trying to do.
                  Thank you very much for your support.

                  Pablo J. RoginaP Offline
                  Pablo J. RoginaP Offline
                  Pablo J. Rogina
                  wrote on last edited by
                  #8

                  @JaviRodriguez I'd suggest to go through the documentation referred before again. Pay attention to the C++ signal and how that signal is handled in QML

                  Upvote the answer(s) that helped you solve the issue
                  Use "Topic Tools" button to mark your post as Solved
                  Add screenshots via postimage.org
                  Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

                  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