Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Help with timer and JavaScript slot.
QtWS25 Last Chance

Help with timer and JavaScript slot.

Scheduled Pinned Locked Moved Solved General and Desktop
43 Posts 4 Posters 5.3k 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.
  • SPlattenS Offline
    SPlattenS Offline
    SPlatten
    wrote on last edited by
    #1

    In my C++ engine I create an instance of QTimer that connects to a JavaScript function. The timer creation is ok and works but the slot isn't being called when the timeout signal occurs and I can see that I am getting the error:

    QObject: Cannot create children for a parent that is in a different thread.
    

    The timer is created with:

    ptmrScript = new QTimer;
    

    I'm using the QJSEngine and connecting the signal and slot:

    QMetaObject::Connection cn = QObject::connect(ptmrScript
                                                 ,&QTimer::timeout
                                                 ,[pobjScriptEng
                                                 ,crstrID
                                                 ,strScript
                                                 ,slstScript]() {
        ...
    

    I've also tried creating the timer using a pointer to QJSEngine:

    ptmrScript = new QTimer(pobjScriptEng);
    

    Same result, how can I fix this as the JavaScript slot isn't being called.

    Kind Regards,
    Sy

    kshegunovK 1 Reply Last reply
    0
    • SPlattenS SPlatten

      @kshegunov, this is how it is now:

      QJSEngine* pobjScriptEng(clsJSON::pobjGetScriptEng());
      QThread* pobjScriptEngThread(pobjScriptEng->thread());
      //Create new timer
      ptmrScript = new QTimer();
      ptmrScript->moveToThread(pobjScriptEngThread);
      ptmrScript->setInterval(cuintInterval);
      

      Have just modified to:

      QJSEngine* pobjScriptEng(clsJSON::pobjGetScriptEng());
      QThread* pobjScriptEngThread(pobjScriptEng->thread());
      //Create new timer
      ptmrScript = new QTimer();
      ptmrScript->setParent(pobjScriptEng);
      ptmrScript->moveToThread(pobjScriptEngThread);
      ptmrScript->setInterval(cuintInterval);
      

      Output is still:

      S000000000027E000000000743T09:24:17.520DL00000202Fsimon2.js[void clsScriptHelper::log]
      setupForm() !!!!
      S000000000028E000000000743T09:24:17.520W:QObject::setParent: Cannot set parent, new parent is in a different thread
      S000000000029E000000000743T09:24:17.520DL00000207Fsimon2.js[void clsScriptHelper::log]
      setupForm() !!!!
      
      KroMignonK Offline
      KroMignonK Offline
      KroMignon
      wrote on last edited by KroMignon
      #40

      @SPlatten I am always surprised how complicated you are trying to solve common issues.

      What is the real issue here?
      You want to create a timer in a specific thread and start it. I am right?
      QTimer muss be started, and stopped from the owned thread.
      That's not so complicated to solve:

      auto myTimer = new  QTimer();
      connect(myTimer; &QTimer::timeout, ...);
      // move to thread
      myTimer->moveToThread(theWorkingThread);
      
      // start the timer
      QTimer::singleShot(0, myTimer, [myTimer]() { myTimer->start(); } );
      

      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

      SPlattenS 1 Reply Last reply
      1
      • SPlattenS SPlatten

        In my C++ engine I create an instance of QTimer that connects to a JavaScript function. The timer creation is ok and works but the slot isn't being called when the timeout signal occurs and I can see that I am getting the error:

        QObject: Cannot create children for a parent that is in a different thread.
        

        The timer is created with:

        ptmrScript = new QTimer;
        

        I'm using the QJSEngine and connecting the signal and slot:

        QMetaObject::Connection cn = QObject::connect(ptmrScript
                                                     ,&QTimer::timeout
                                                     ,[pobjScriptEng
                                                     ,crstrID
                                                     ,strScript
                                                     ,slstScript]() {
            ...
        

        I've also tried creating the timer using a pointer to QJSEngine:

        ptmrScript = new QTimer(pobjScriptEng);
        

        Same result, how can I fix this as the JavaScript slot isn't being called.

        kshegunovK Offline
        kshegunovK Offline
        kshegunov
        Moderators
        wrote on last edited by
        #2

        It's a runtime error, so I can't tell if this is the correct piece of code you're showing us. So:

        If the QT_FATAL_WARNINGS environment variable is set, qWarning() exits after printing the warning message. This makes it easy to obtain a backtrace in the debugger.

        From https://doc.qt.io/qt-5/debug.html.

        Set the environment variable and extract a stack trace; paste the trace here and we can talk more.

        Read and abide by the Qt Code of Conduct

        SPlattenS 1 Reply Last reply
        0
        • kshegunovK kshegunov

          It's a runtime error, so I can't tell if this is the correct piece of code you're showing us. So:

          If the QT_FATAL_WARNINGS environment variable is set, qWarning() exits after printing the warning message. This makes it easy to obtain a backtrace in the debugger.

          From https://doc.qt.io/qt-5/debug.html.

          Set the environment variable and extract a stack trace; paste the trace here and we can talk more.

          SPlattenS Offline
          SPlattenS Offline
          SPlatten
          wrote on last edited by SPlatten
          #3

          @kshegunov , I will look at the link and get back to you.

          I added:

          export QT_DEBUG_PLUGINS=1
          export QT_FATAL_WARNINGS=1
          

          To ~/.profile, I also went to Project Settings -> Environment and added the same environment variables to Qt Creator.

          When I build my project now it terminates instantly, this is the application output:

          2021-12-30 07:06:58.865187+0000 XMLMPAM[5523:56476] QFactoryLoader::QFactoryLoader() checking directory path "/Users/sy/Qt/5.15.2/clang_64/plugins/platforms" ...
          2021-12-30 07:06:58.874330+0000 XMLMPAM[5523:56476] QFactoryLoader::QFactoryLoader() looking at "/Users/sy/Qt/5.15.2/clang_64/plugins/platforms/libqcocoa.dylib"
          2021-12-30 07:06:58.874511+0000 XMLMPAM[5523:56476] Found metadata in lib /Users/sy/Qt/5.15.2/clang_64/plugins/platforms/libqcocoa.dylib, metadata=
          {
              "IID": "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.3",
              "MetaData": {
                  "Keys": [
                      "cocoa"
                  ]
              },
              "archreq": 0,
              "className": "QCocoaIntegrationPlugin",
              "debug": false,
              "version": 331520
          }
          

          This looks like a different issue...I've reverted from implementing these environment variables as this isn't the same issue and I cannot use these to get where I need to be to fault find.

          It seems the issue I'm having is using a lambda JavaScript function with the timer signal, can anyone help?

          Kind Regards,
          Sy

          JonBJ kshegunovK 2 Replies Last reply
          0
          • SPlattenS SPlatten

            @kshegunov , I will look at the link and get back to you.

            I added:

            export QT_DEBUG_PLUGINS=1
            export QT_FATAL_WARNINGS=1
            

            To ~/.profile, I also went to Project Settings -> Environment and added the same environment variables to Qt Creator.

            When I build my project now it terminates instantly, this is the application output:

            2021-12-30 07:06:58.865187+0000 XMLMPAM[5523:56476] QFactoryLoader::QFactoryLoader() checking directory path "/Users/sy/Qt/5.15.2/clang_64/plugins/platforms" ...
            2021-12-30 07:06:58.874330+0000 XMLMPAM[5523:56476] QFactoryLoader::QFactoryLoader() looking at "/Users/sy/Qt/5.15.2/clang_64/plugins/platforms/libqcocoa.dylib"
            2021-12-30 07:06:58.874511+0000 XMLMPAM[5523:56476] Found metadata in lib /Users/sy/Qt/5.15.2/clang_64/plugins/platforms/libqcocoa.dylib, metadata=
            {
                "IID": "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.3",
                "MetaData": {
                    "Keys": [
                        "cocoa"
                    ]
                },
                "archreq": 0,
                "className": "QCocoaIntegrationPlugin",
                "debug": false,
                "version": 331520
            }
            

            This looks like a different issue...I've reverted from implementing these environment variables as this isn't the same issue and I cannot use these to get where I need to be to fault find.

            It seems the issue I'm having is using a lambda JavaScript function with the timer signal, can anyone help?

            JonBJ Online
            JonBJ Online
            JonB
            wrote on last edited by JonB
            #4

            @SPlatten said in Help with timer and JavaScript slot.:

            It seems the issue I'm having is using a lambda JavaScript function with the timer signal, can anyone help?

            I'm afraid I do not have the solution, but have you at least verified this claim? You may well be right, but why don't you temporarily test with a regular function slot so you know whether lambda is relevant to the issue? And a lambda slot on a non-timer signal.

            SPlattenS 1 Reply Last reply
            0
            • JonBJ JonB

              @SPlatten said in Help with timer and JavaScript slot.:

              It seems the issue I'm having is using a lambda JavaScript function with the timer signal, can anyone help?

              I'm afraid I do not have the solution, but have you at least verified this claim? You may well be right, but why don't you temporarily test with a regular function slot so you know whether lambda is relevant to the issue? And a lambda slot on a non-timer signal.

              SPlattenS Offline
              SPlattenS Offline
              SPlatten
              wrote on last edited by
              #5

              @JonB , I know the timer and connection to a slot works perfectly fine as I use this technique elsewhere.

              Kind Regards,
              Sy

              JonBJ 1 Reply Last reply
              0
              • SPlattenS SPlatten

                @kshegunov , I will look at the link and get back to you.

                I added:

                export QT_DEBUG_PLUGINS=1
                export QT_FATAL_WARNINGS=1
                

                To ~/.profile, I also went to Project Settings -> Environment and added the same environment variables to Qt Creator.

                When I build my project now it terminates instantly, this is the application output:

                2021-12-30 07:06:58.865187+0000 XMLMPAM[5523:56476] QFactoryLoader::QFactoryLoader() checking directory path "/Users/sy/Qt/5.15.2/clang_64/plugins/platforms" ...
                2021-12-30 07:06:58.874330+0000 XMLMPAM[5523:56476] QFactoryLoader::QFactoryLoader() looking at "/Users/sy/Qt/5.15.2/clang_64/plugins/platforms/libqcocoa.dylib"
                2021-12-30 07:06:58.874511+0000 XMLMPAM[5523:56476] Found metadata in lib /Users/sy/Qt/5.15.2/clang_64/plugins/platforms/libqcocoa.dylib, metadata=
                {
                    "IID": "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.3",
                    "MetaData": {
                        "Keys": [
                            "cocoa"
                        ]
                    },
                    "archreq": 0,
                    "className": "QCocoaIntegrationPlugin",
                    "debug": false,
                    "version": 331520
                }
                

                This looks like a different issue...I've reverted from implementing these environment variables as this isn't the same issue and I cannot use these to get where I need to be to fault find.

                It seems the issue I'm having is using a lambda JavaScript function with the timer signal, can anyone help?

                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by
                #6

                @SPlatten said in Help with timer and JavaScript slot.:

                export QT_DEBUG_PLUGINS=1

                I didn't say you should include this. This is when you're attempting to track errors in the plugins loading, you're not, are you?

                Read and abide by the Qt Code of Conduct

                SPlattenS 1 Reply Last reply
                1
                • SPlattenS SPlatten

                  @JonB , I know the timer and connection to a slot works perfectly fine as I use this technique elsewhere.

                  JonBJ Online
                  JonBJ Online
                  JonB
                  wrote on last edited by
                  #7

                  @SPlatten
                  Based on nothing, I'd find it "surprising" if the existence of a lambda in itself causes a thread to be spawned/involved.

                  Meantime I think you should follow @kshegunov's request: test QT_FATAL_WARNINGS=1 but not with QT_DEBUG_PLUGINS=1.

                  SPlattenS 1 Reply Last reply
                  0
                  • kshegunovK kshegunov

                    @SPlatten said in Help with timer and JavaScript slot.:

                    export QT_DEBUG_PLUGINS=1

                    I didn't say you should include this. This is when you're attempting to track errors in the plugins loading, you're not, are you?

                    SPlattenS Offline
                    SPlattenS Offline
                    SPlatten
                    wrote on last edited by
                    #8

                    @kshegunov , with just:

                    QT_FATAL_WARNINGS
                    

                    set to 1, I don't get the initial problem however the result is no different and in my debug output I still get:

                    S000000000029E000000002424T08:09:54.416W:QObject: Cannot create children for a parent that is in a different thread.
                    (Parent is QNativeSocketEngine(0x6000000122f0), parent's thread is clsServer(0x600000252c00), current thread is clsThread(0x600002632700)
                    S000000000030E000000002424T08:09:54.416W:QObject: Cannot create children for a parent that is in a different thread.
                    (Parent is QNativeSocketEngine(0x600000014140), parent's thread is clsServer(0x600000252140), current thread is clsThread(0x600002632700)
                    S000000000031E000000002424T08:09:54.416W:QObject: Cannot create children for a parent that is in a different thread.
                    (Parent is QNativeSocketEngine(0x60000000b0b0), parent's thread is clsServer(0x600000250b60), current thread is clsThread(0x600002632700)
                    

                    Where everything before : is my own tracking information.

                    Kind Regards,
                    Sy

                    kshegunovK 1 Reply Last reply
                    0
                    • JonBJ JonB

                      @SPlatten
                      Based on nothing, I'd find it "surprising" if the existence of a lambda in itself causes a thread to be spawned/involved.

                      Meantime I think you should follow @kshegunov's request: test QT_FATAL_WARNINGS=1 but not with QT_DEBUG_PLUGINS=1.

                      SPlattenS Offline
                      SPlattenS Offline
                      SPlatten
                      wrote on last edited by SPlatten
                      #9

                      @JonB I think the thread is related to the JavaScript function call in the Lambda:

                      QMetaObject::Connection cn = QObject::connect(ptmrScript
                                                                   ,&QTimer::timeout
                                                                   ,[pobjScriptEng
                                                                   ,ptmrScript
                                                                   ,strFile
                                                                   ,strFunc
                                                                   ,strScriptWithCall]() {
                         QJSValue objResult(pobjScriptEng->evaluate(strScriptWithCall));
                         QString strError;
                         if ( objResult.isError() == true ) {
                             strError = QString("%1\n%2\n%3").arg(strFile).arg(strFunc)
                                                             .arg(objResult.toString());
                         } else {
                             QString strResult(objResult.toString());
                             if ( strResult.compare("undefined") != 0 ) {
                                 strError = strResult;
                             }
                          }
                          if ( strError.isEmpty() != true ) {
                              clsXMLnode* pobjRoot(clsXMLnode::spobjGetRoot());
                              emit pobjRoot->error(strError);
                              ptmrScript->deleteLater();
                          }
                      });
                      

                      Kind Regards,
                      Sy

                      JonBJ 1 Reply Last reply
                      0
                      • SPlattenS SPlatten

                        @JonB I think the thread is related to the JavaScript function call in the Lambda:

                        QMetaObject::Connection cn = QObject::connect(ptmrScript
                                                                     ,&QTimer::timeout
                                                                     ,[pobjScriptEng
                                                                     ,ptmrScript
                                                                     ,strFile
                                                                     ,strFunc
                                                                     ,strScriptWithCall]() {
                           QJSValue objResult(pobjScriptEng->evaluate(strScriptWithCall));
                           QString strError;
                           if ( objResult.isError() == true ) {
                               strError = QString("%1\n%2\n%3").arg(strFile).arg(strFunc)
                                                               .arg(objResult.toString());
                           } else {
                               QString strResult(objResult.toString());
                               if ( strResult.compare("undefined") != 0 ) {
                                   strError = strResult;
                               }
                            }
                            if ( strError.isEmpty() != true ) {
                                clsXMLnode* pobjRoot(clsXMLnode::spobjGetRoot());
                                emit pobjRoot->error(strError);
                                ptmrScript->deleteLater();
                            }
                        });
                        
                        JonBJ Online
                        JonBJ Online
                        JonB
                        wrote on last edited by JonB
                        #10

                        @SPlatten
                        I just don't see where/why a lambda will behave differently from a C++ method here, as you say it does. Maybe your issue lies in the calls of the body of the lambda, which is a different matter, and ought show up equally in a method instead.

                        But ignore me because I won't have a solution. @kshegunov is much more likely to spot/offer one... :)

                        1 Reply Last reply
                        0
                        • SPlattenS SPlatten

                          @kshegunov , with just:

                          QT_FATAL_WARNINGS
                          

                          set to 1, I don't get the initial problem however the result is no different and in my debug output I still get:

                          S000000000029E000000002424T08:09:54.416W:QObject: Cannot create children for a parent that is in a different thread.
                          (Parent is QNativeSocketEngine(0x6000000122f0), parent's thread is clsServer(0x600000252c00), current thread is clsThread(0x600002632700)
                          S000000000030E000000002424T08:09:54.416W:QObject: Cannot create children for a parent that is in a different thread.
                          (Parent is QNativeSocketEngine(0x600000014140), parent's thread is clsServer(0x600000252140), current thread is clsThread(0x600002632700)
                          S000000000031E000000002424T08:09:54.416W:QObject: Cannot create children for a parent that is in a different thread.
                          (Parent is QNativeSocketEngine(0x60000000b0b0), parent's thread is clsServer(0x600000250b60), current thread is clsThread(0x600002632700)
                          

                          Where everything before : is my own tracking information.

                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by
                          #11

                          @SPlatten said in Help with timer and JavaScript slot.:

                          I don't get the initial problem however the result is no different and in my debug output I still get:

                          It is not a fix, it's a technique to track down where the problem occurs. Also, "debug output" != "stack trace". When the debugger trips the assertion with QT_FATAL_WARNINGS on it's going to stop in all threads. Then you can go to creator's call stack view (or whatever IDE you're using) and you can extract the exact backtrace, which is what I requested. I don't expect the output the change, as nothing's been done at this point beside making the program crash, instead of silently (and wrongfully) succeeding.

                          @JonB I think the thread is related to the JavaScript function call in the Lambda

                          Why? How do you figure this out? I have no indication that this is where the warning's been emitted, it can be anyplace else.

                          Read and abide by the Qt Code of Conduct

                          SPlattenS 1 Reply Last reply
                          1
                          • kshegunovK kshegunov

                            @SPlatten said in Help with timer and JavaScript slot.:

                            I don't get the initial problem however the result is no different and in my debug output I still get:

                            It is not a fix, it's a technique to track down where the problem occurs. Also, "debug output" != "stack trace". When the debugger trips the assertion with QT_FATAL_WARNINGS on it's going to stop in all threads. Then you can go to creator's call stack view (or whatever IDE you're using) and you can extract the exact backtrace, which is what I requested. I don't expect the output the change, as nothing's been done at this point beside making the program crash, instead of silently (and wrongfully) succeeding.

                            @JonB I think the thread is related to the JavaScript function call in the Lambda

                            Why? How do you figure this out? I have no indication that this is where the warning's been emitted, it can be anyplace else.

                            SPlattenS Offline
                            SPlattenS Offline
                            SPlatten
                            wrote on last edited by
                            #12

                            @kshegunov , please see edit of my last post which includes the body of the lambda. The execution doesn't stop, there is just output to the debug.

                            Kind Regards,
                            Sy

                            kshegunovK 1 Reply Last reply
                            0
                            • SPlattenS SPlatten

                              @kshegunov , please see edit of my last post which includes the body of the lambda. The execution doesn't stop, there is just output to the debug.

                              kshegunovK Offline
                              kshegunovK Offline
                              kshegunov
                              Moderators
                              wrote on last edited by kshegunov
                              #13

                              @SPlatten said in Help with timer and JavaScript slot.:

                              @kshegunov , please see edit of my last post which includes the body of the lambda. The execution doesn't stop, there is just output to the debug.

                              I have a fairly good idea where the problem may be, but I prefer not to speculate at this point. If the program doesn't stop and the mentioned environment variable is set, then you're not running your application in debug mode - check this and adjust accordingly.

                              Read and abide by the Qt Code of Conduct

                              SPlattenS 1 Reply Last reply
                              0
                              • kshegunovK kshegunov

                                @SPlatten said in Help with timer and JavaScript slot.:

                                @kshegunov , please see edit of my last post which includes the body of the lambda. The execution doesn't stop, there is just output to the debug.

                                I have a fairly good idea where the problem may be, but I prefer not to speculate at this point. If the program doesn't stop and the mentioned environment variable is set, then you're not running your application in debug mode - check this and adjust accordingly.

                                SPlattenS Offline
                                SPlattenS Offline
                                SPlatten
                                wrote on last edited by SPlatten
                                #14

                                @kshegunov , 100% I'm in debug, I'm running in Qt Creator debug and developing. I have a function called createTimer here is the prototype:

                                Q_INVOKABLE void createTimer(const QString& crstrID
                                                            ,const uint cuintInterval
                                                            ,const QString& crstrFunction);
                                

                                The implementation:

                                /**
                                 * @brief clsScriptHelper::createTimer
                                 * @param crstrID : Constant reference to Timer ID
                                 * @param cuintInterval : Constant millisecond interval
                                 * @param crstrFunction : Constant reference to JSfile@Function
                                 */
                                void clsScriptHelper::createTimer(const QString& crstrID, const uint cuintInterval
                                                                 ,const QString& crstrFunction) {
                                    if ( crstrID.trimmed().isEmpty() == true || cuintInterval == 0
                                      || crstrFunction.trimmed().isEmpty() == true
                                      || crstrFunction.indexOf(clsXMLnode::msccScriptDelimiter) == -1 ) {
                                    //One or more of the parameters are invalid, do nothing
                                        return;
                                    }
                                    //Get Application instance
                                    clsMainWnd* pAppInstance(clsMainWnd::pobjGetAppWnd());
                                    if ( pAppInstance == nullptr ) {
                                    //Cannot get application instance!
                                        return;
                                    }
                                    //Look for registered timer
                                    QTimer* ptmrScript(pAppInstance->ptmrGetTimer(crstrID));
                                    if ( ptmrScript != nullptr ) {
                                    //Already registered, do nothing
                                        return;
                                    }
                                    //No timer locatd with that ID, its safe to proceed
                                    QStringList slstScript = crstrFunction.split(clsXMLnode::msccScriptDelimiter);
                                    mpScripts* pmpScriptsMap;
                                    if ( slstScript.length() == SSF_PARAM_COUNT
                                    && (pmpScriptsMap = clsMainWnd::pmpGetScriptsMap()) != nullptr ) {
                                    //Look for the script in the scripts map
                                        mpScripts::iterator itrScript(pmpScriptsMap->find(slstScript[SFF_FILE_IDX]));
                                        if ( itrScript != pmpScriptsMap->end() ) {
                                    //Found it, build the script up ready for the signal connection
                                            QString strScript(itrScript->second);
                                    //Get pointer to script engine
                                            QJSEngine* pobjScriptEng(clsJSON::pobjGetScriptEng());
                                    //Create new timer
                                            ptmrScript = new QTimer();
                                    //Register the new timer using the supplied ID
                                            pAppInstance->registerTimer(ptmrScript, crstrID);
                                    //Add any globals to the script
                                            clsScriptHelper::pobjGetInstance()->addGlobals(pobjScriptEng);
                                    //Build up script function call
                                            QString strFile(slstScript[SFF_FILE_IDX])
                                                   ,strCall(slstScript[SSF_FUNCTION_IDX])
                                                   ,strScriptWithCall(strScript)
                                                   ,strFunc(strCall
                                                          + QString(clsDebugService::msccBrktOpen)
                                                          + QString(clsDebugService::msccBrktClose)
                                                          + QString(clsXMLnode::msccScriptFunctionTerminator));
                                             if ( strScriptWithCall.endsWith(clsXMLnode::msccScriptFunctionTerminator) != true ) {
                                                 strScriptWithCall += clsXMLnode::msccScriptFunctionTerminator;
                                             }
                                             strScriptWithCall += strFunc;
                                    //Create connection to timer and script
                                            QMetaObject::Connection cn = QObject::connect(ptmrScript
                                                                                         ,&QTimer::timeout
                                                                                         ,[pobjScriptEng
                                                                                          ,ptmrScript
                                                                                          ,strFile
                                                                                          ,strFunc
                                                                                          ,strScriptWithCall]() {
                                                 QJSValue objResult(pobjScriptEng->evaluate(strScriptWithCall));
                                                 QString strError;
                                                 if ( objResult.isError() == true ) {
                                                     strError = QString("%1\n%2\n%3").arg(strFile).arg(strFunc)
                                                                                     .arg(objResult.toString());
                                                 } else {
                                                     QString strResult(objResult.toString());
                                                     if ( strResult.compare("undefined") != 0 ) {
                                                         strError = strResult;
                                                     }
                                                 }
                                                 if ( strError.isEmpty() != true ) {
                                                     clsXMLnode* pobjRoot(clsXMLnode::spobjGetRoot());
                                                     emit pobjRoot->error(strError);
                                                     ptmrScript->deleteLater();
                                                 }
                                            });
                                    //Start the timer
                                            ptmrScript->start(cuintInterval);
                                        }
                                    }
                                }
                                

                                In my JavaScript I call the C++ function:

                                xmleng.createTimer("t1", 50, "simon2.js@testTimer");
                                

                                The JavaScript lambda function, it doesn't get called because the slot doesn't get called:

                                function testTimer() {
                                    //All properties area stored as strings, convert to integer
                                    var intStageCtr = parseInt(xmleng.getProperty(cstrFormTest, cstrStageCtr));	
                                    xmleng.log(0, "testTimer[" + intStageCtr + "]", cstrThis, 316);
                                    //Increment stage counter
                                    intStageCtr++;
                                    //Convert back to string and store
                                    xmleng.setProperty(cstrFormTest, cstrStageCtr, String(intStageCtr));
                                }
                                

                                Kind Regards,
                                Sy

                                kshegunovK 1 Reply Last reply
                                0
                                • SPlattenS SPlatten

                                  @kshegunov , 100% I'm in debug, I'm running in Qt Creator debug and developing. I have a function called createTimer here is the prototype:

                                  Q_INVOKABLE void createTimer(const QString& crstrID
                                                              ,const uint cuintInterval
                                                              ,const QString& crstrFunction);
                                  

                                  The implementation:

                                  /**
                                   * @brief clsScriptHelper::createTimer
                                   * @param crstrID : Constant reference to Timer ID
                                   * @param cuintInterval : Constant millisecond interval
                                   * @param crstrFunction : Constant reference to JSfile@Function
                                   */
                                  void clsScriptHelper::createTimer(const QString& crstrID, const uint cuintInterval
                                                                   ,const QString& crstrFunction) {
                                      if ( crstrID.trimmed().isEmpty() == true || cuintInterval == 0
                                        || crstrFunction.trimmed().isEmpty() == true
                                        || crstrFunction.indexOf(clsXMLnode::msccScriptDelimiter) == -1 ) {
                                      //One or more of the parameters are invalid, do nothing
                                          return;
                                      }
                                      //Get Application instance
                                      clsMainWnd* pAppInstance(clsMainWnd::pobjGetAppWnd());
                                      if ( pAppInstance == nullptr ) {
                                      //Cannot get application instance!
                                          return;
                                      }
                                      //Look for registered timer
                                      QTimer* ptmrScript(pAppInstance->ptmrGetTimer(crstrID));
                                      if ( ptmrScript != nullptr ) {
                                      //Already registered, do nothing
                                          return;
                                      }
                                      //No timer locatd with that ID, its safe to proceed
                                      QStringList slstScript = crstrFunction.split(clsXMLnode::msccScriptDelimiter);
                                      mpScripts* pmpScriptsMap;
                                      if ( slstScript.length() == SSF_PARAM_COUNT
                                      && (pmpScriptsMap = clsMainWnd::pmpGetScriptsMap()) != nullptr ) {
                                      //Look for the script in the scripts map
                                          mpScripts::iterator itrScript(pmpScriptsMap->find(slstScript[SFF_FILE_IDX]));
                                          if ( itrScript != pmpScriptsMap->end() ) {
                                      //Found it, build the script up ready for the signal connection
                                              QString strScript(itrScript->second);
                                      //Get pointer to script engine
                                              QJSEngine* pobjScriptEng(clsJSON::pobjGetScriptEng());
                                      //Create new timer
                                              ptmrScript = new QTimer();
                                      //Register the new timer using the supplied ID
                                              pAppInstance->registerTimer(ptmrScript, crstrID);
                                      //Add any globals to the script
                                              clsScriptHelper::pobjGetInstance()->addGlobals(pobjScriptEng);
                                      //Build up script function call
                                              QString strFile(slstScript[SFF_FILE_IDX])
                                                     ,strCall(slstScript[SSF_FUNCTION_IDX])
                                                     ,strScriptWithCall(strScript)
                                                     ,strFunc(strCall
                                                            + QString(clsDebugService::msccBrktOpen)
                                                            + QString(clsDebugService::msccBrktClose)
                                                            + QString(clsXMLnode::msccScriptFunctionTerminator));
                                               if ( strScriptWithCall.endsWith(clsXMLnode::msccScriptFunctionTerminator) != true ) {
                                                   strScriptWithCall += clsXMLnode::msccScriptFunctionTerminator;
                                               }
                                               strScriptWithCall += strFunc;
                                      //Create connection to timer and script
                                              QMetaObject::Connection cn = QObject::connect(ptmrScript
                                                                                           ,&QTimer::timeout
                                                                                           ,[pobjScriptEng
                                                                                            ,ptmrScript
                                                                                            ,strFile
                                                                                            ,strFunc
                                                                                            ,strScriptWithCall]() {
                                                   QJSValue objResult(pobjScriptEng->evaluate(strScriptWithCall));
                                                   QString strError;
                                                   if ( objResult.isError() == true ) {
                                                       strError = QString("%1\n%2\n%3").arg(strFile).arg(strFunc)
                                                                                       .arg(objResult.toString());
                                                   } else {
                                                       QString strResult(objResult.toString());
                                                       if ( strResult.compare("undefined") != 0 ) {
                                                           strError = strResult;
                                                       }
                                                   }
                                                   if ( strError.isEmpty() != true ) {
                                                       clsXMLnode* pobjRoot(clsXMLnode::spobjGetRoot());
                                                       emit pobjRoot->error(strError);
                                                       ptmrScript->deleteLater();
                                                   }
                                              });
                                      //Start the timer
                                              ptmrScript->start(cuintInterval);
                                          }
                                      }
                                  }
                                  

                                  In my JavaScript I call the C++ function:

                                  xmleng.createTimer("t1", 50, "simon2.js@testTimer");
                                  

                                  The JavaScript lambda function, it doesn't get called because the slot doesn't get called:

                                  function testTimer() {
                                      //All properties area stored as strings, convert to integer
                                      var intStageCtr = parseInt(xmleng.getProperty(cstrFormTest, cstrStageCtr));	
                                      xmleng.log(0, "testTimer[" + intStageCtr + "]", cstrThis, 316);
                                      //Increment stage counter
                                      intStageCtr++;
                                      //Convert back to string and store
                                      xmleng.setProperty(cstrFormTest, cstrStageCtr, String(intStageCtr));
                                  }
                                  
                                  kshegunovK Offline
                                  kshegunovK Offline
                                  kshegunov
                                  Moderators
                                  wrote on last edited by kshegunov
                                  #15

                                  Put a breakpoint in clsMainWnd::ptmrGetTimer and confirm it gets triggered (the breakpoint).

                                  Additionally provide its source, and finally add this to the very beginning of the mentioned function:

                                  qDebug() << QThread::currentThread();
                                  

                                  Read and abide by the Qt Code of Conduct

                                  SPlattenS 1 Reply Last reply
                                  0
                                  • kshegunovK kshegunov

                                    Put a breakpoint in clsMainWnd::ptmrGetTimer and confirm it gets triggered (the breakpoint).

                                    Additionally provide its source, and finally add this to the very beginning of the mentioned function:

                                    qDebug() << QThread::currentThread();
                                    
                                    SPlattenS Offline
                                    SPlattenS Offline
                                    SPlatten
                                    wrote on last edited by SPlatten
                                    #16

                                    @kshegunov , I've stepped through this logic, I expect the initial call to ptmrGetTimer to return nullptr as on first call the timer won't be registered which it isn't. I've stepped through the logic to the line:

                                    ptmrScript->start(cuintInterval);
                                    

                                    No issues except the slot isn't called when the timer expires. And the mentioned debug output.

                                    Kind Regards,
                                    Sy

                                    kshegunovK 1 Reply Last reply
                                    0
                                    • SPlattenS SPlatten

                                      @kshegunov , I've stepped through this logic, I expect the initial call to ptmrGetTimer to return nullptr as on first call the timer won't be registered which it isn't. I've stepped through the logic to the line:

                                      ptmrScript->start(cuintInterval);
                                      

                                      No issues except the slot isn't called when the timer expires. And the mentioned debug output.

                                      kshegunovK Offline
                                      kshegunovK Offline
                                      kshegunov
                                      Moderators
                                      wrote on last edited by
                                      #17

                                      @SPlatten said in Help with timer and JavaScript slot.:

                                      @kshegunov , I've stepped through this logic, I expect the initial call to ptmrGetTimer to return nullptr as on first call the timer won't be registered which it isn't.

                                      I requested something very specific with a very specific purpose. Please do what I asked and provide the output of the mentioned qDebug call.

                                      Read and abide by the Qt Code of Conduct

                                      SPlattenS 1 Reply Last reply
                                      0
                                      • kshegunovK kshegunov

                                        @SPlatten said in Help with timer and JavaScript slot.:

                                        @kshegunov , I've stepped through this logic, I expect the initial call to ptmrGetTimer to return nullptr as on first call the timer won't be registered which it isn't.

                                        I requested something very specific with a very specific purpose. Please do what I asked and provide the output of the mentioned qDebug call.

                                        SPlattenS Offline
                                        SPlattenS Offline
                                        SPlatten
                                        wrote on last edited by SPlatten
                                        #18

                                        @kshegunov Adding this now. I've actually changed the code to add:

                                        QThread* pobjCurrThread(QThread::currentThread());
                                        //Create new timer
                                        ptmrScript = new QTimer();
                                        ptmrScript->moveToThread(pobjCurrThread);
                                        qdbg() << "pobjCurrThread: " << pobjCurrThread;
                                        

                                        Output:

                                        pobjCurrThread: QThread(0x600000269c80)
                                        

                                        I have a breakpoint in the lambda function, first line, it doesn't get triggered.

                                        Kind Regards,
                                        Sy

                                        kshegunovK 1 Reply Last reply
                                        0
                                        • SPlattenS SPlatten

                                          @kshegunov Adding this now. I've actually changed the code to add:

                                          QThread* pobjCurrThread(QThread::currentThread());
                                          //Create new timer
                                          ptmrScript = new QTimer();
                                          ptmrScript->moveToThread(pobjCurrThread);
                                          qdbg() << "pobjCurrThread: " << pobjCurrThread;
                                          

                                          Output:

                                          pobjCurrThread: QThread(0x600000269c80)
                                          

                                          I have a breakpoint in the lambda function, first line, it doesn't get triggered.

                                          kshegunovK Offline
                                          kshegunovK Offline
                                          kshegunov
                                          Moderators
                                          wrote on last edited by
                                          #19

                                          @SPlatten said in Help with timer and JavaScript slot.:

                                          I have a breakpoint in the lambda function, first line, it doesn't get triggered.

                                          I don't expect it to get trigerred, but again, this is not what I wrote. Here's a reminder:

                                          Put a breakpoint in clsMainWnd::ptmrGetTimer and confirm it gets triggered (the breakpoint).

                                          Additionally provide its source, and finally add this to the very beginning of the mentioned function:
                                          [snip]

                                          Read and abide by the Qt Code of Conduct

                                          SPlattenS 3 Replies Last reply
                                          0
                                          • kshegunovK kshegunov

                                            @SPlatten said in Help with timer and JavaScript slot.:

                                            I have a breakpoint in the lambda function, first line, it doesn't get triggered.

                                            I don't expect it to get trigerred, but again, this is not what I wrote. Here's a reminder:

                                            Put a breakpoint in clsMainWnd::ptmrGetTimer and confirm it gets triggered (the breakpoint).

                                            Additionally provide its source, and finally add this to the very beginning of the mentioned function:
                                            [snip]

                                            SPlattenS Offline
                                            SPlattenS Offline
                                            SPlatten
                                            wrote on last edited by
                                            #20

                                            @kshegunov , here is there requested source to the function:

                                            /**
                                             * @brief clsMainWnd::ptmrGetTimer
                                             * @param crstrID : Constant reference to ID to look-up timer
                                             * @return A pointer to the timer or nullptr if not found
                                             */
                                            QTimer* clsMainWnd::ptmrGetTimer(const QString& crstrID) {
                                                mpTimers::iterator itTimer(mmpTimers.find(crstrID));
                                                QTimer* pTimer(nullptr);
                                                if ( itTimer != mmpTimers.end() ) {
                                                    pTimer = itTimer->second;
                                                }
                                                return pTimer;
                                            }
                                            

                                            I put breakpoint on first line of this, it does what I expected, nullptr is returned because on the first call the timer hasn't been registered.

                                            Kind Regards,
                                            Sy

                                            SPlattenS 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