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. Unable to assign QJSValue to QString
Forum Updated to NodeBB v4.3 + New Features

Unable to assign QJSValue to QString

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
workerscript
10 Posts 3 Posters 14.9k Views 1 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.
  • M Offline
    M Offline
    MarcVanDaele
    wrote on 14 Dec 2015, 14:21 last edited by
    #1

    In my example application (see below) consisting of a main.qml and a simple WorkerScript re I run into the exception Unable to assign QJSValue to QString in the line text: listview.model.get(index).title2
    I also tried using title2() but this resulted in
    TypeError: Property 'title2' of object ModelObject(0x7faa22cc83c0) is not a function

    Is this caused by my lack of Javascript knowledge or is this a limitation of the QML/JS interface?

    My main.qml is

    import QtQuick 2.3
    import QtQuick.Window 2.2
    
    Window {
        visible: true
        width: 600
        height: 360
    
        ListView {
            id: listview
            anchors.fill: parent
            model: ListModel {
                id: channelList_model
            }
            delegate: Text {
                text: listview.model.get(index).title2
            }
        }
    
        Component.onCompleted: {
            var msg = {'model': channelList_model};
            worker.sendMessage(msg);
        }
    
        WorkerScript {
            id: worker
            source: "getObjects.js"
        }
    }
    

    and my getObjects.js file looks like

    function SomeObject(title){
        this.title = title
        this.title2 = function() {return "another title";};
    }
    
    WorkerScript.onMessage = function(msg) {
         var someObject   = new SomeObject("SomeTitle")
         msg.model.append(someObject)
         msg.model.sync()
    }
    
    1 Reply Last reply
    1
    • M Offline
      M Offline
      MarcVanDaele
      wrote on 14 Dec 2015, 15:55 last edited by
      #2

      I experimented a bit more and the issue is not related to WorkerScript but somehow seems to be related to ListView.
      Below is one working and one not-working example.
      Can somebody explain this to me?

      The following main.qml works just fine

      import QtQuick 2.3
      import QtQuick.Window 2.2
      
      Window {
          visible: true
          width: 600
          height: 360
          property var someObject : makeSomeObject("SomeTitle")
          function  makeSomeObject(title){
              var obj = {
                      title:  title,
                      title2: function() {return "another title";}
                  };
                  return obj;
          }
      
          Text {
             text: someObject.title2()
          }
      }
      

      while this one, using a ListView, results in the two errors I reported earlier

      import QtQuick 2.3
      import QtQuick.Window 2.2
      
      Window {
          visible: true
          width: 600
          height: 360
          property var someObject : makeSomeObject("SomeTitle")
          function  makeSomeObject(title){
              var obj = {
                      title:  title,
                      title2: function() {return "another title";}
                  };
                  return obj;
          }
      
          ListView {
             anchors.fill: parent
             model: ListModel {id: list_model}
             delegate: Text {text: list_model.get(index).title2}
          }
      
          Component.onCompleted: {
              list_model.append(someObject)
              list_model.append(someObject)
          }
      }
      
      1 Reply Last reply
      0
      • D Offline
        D Offline
        dheerendra
        Qt Champions 2022
        wrote on 15 Dec 2015, 10:09 last edited by
        #3

        Both should give you same problem. Here it is treated like function someObject.title2(). You should call it like someObject.title2. It should end up in same problem.

        Instead of anonymous function I made it like the following and it works fine.

        function callme() {
            return "another title"
        }
            var obj = {
                Title:  Title,
                Title2 : callme()
                //Title2: function () {return "anotherTitle";
            }
        

        Dheerendra
        @Community Service
        Certified Qt Specialist
        http://www.pthinks.com

        M 1 Reply Last reply 15 Dec 2015, 10:57
        4
        • D dheerendra
          15 Dec 2015, 10:09

          Both should give you same problem. Here it is treated like function someObject.title2(). You should call it like someObject.title2. It should end up in same problem.

          Instead of anonymous function I made it like the following and it works fine.

          function callme() {
              return "another title"
          }
              var obj = {
                  Title:  Title,
                  Title2 : callme()
                  //Title2: function () {return "anotherTitle";
              }
          
          M Offline
          M Offline
          MarcVanDaele
          wrote on 15 Dec 2015, 10:57 last edited by
          #4

          @dheerendra Thanks for your input.
          This indeed works but there is a fundamental difference.

          In your solution, the function is evaluated when the object is created.
          While I would like to only call the function when needed (ie when used in a ListView delegate)

          Suppose the model contains 100 objects whereof only 5 are visible: your solution will evaluate the function 100 times while I would like to have only 5 calls.

          1 Reply Last reply
          1
          • D Offline
            D Offline
            dheerendra
            Qt Champions 2022
            wrote on 15 Dec 2015, 11:30 last edited by
            #5

            Confused. Your View is driven by the model. You need build model before you start displaying. So your function is called as many elements exist in the model ? Your function is called 100 times ?

            Dheerendra
            @Community Service
            Certified Qt Specialist
            http://www.pthinks.com

            M 1 Reply Last reply 16 Dec 2015, 11:00
            3
            • D dheerendra
              15 Dec 2015, 11:30

              Confused. Your View is driven by the model. You need build model before you start displaying. So your function is called as many elements exist in the model ? Your function is called 100 times ?

              M Offline
              M Offline
              MarcVanDaele
              wrote on 16 Dec 2015, 11:00 last edited by
              #6

              @dheerendra When returning an object with title2: function() {return "another title";}, the function is created but not evaluated. So the model will contain 100 objects with a function.
              The delegates are only created for the visible elements in the ListView and hence the delegate Text {text: list_model.get(index).title2()} is only created 5 times and hence also the call to title2() is only called 5 times.

              Does this make sense?

              1 Reply Last reply
              0
              • H Offline
                H Offline
                Hamed.Masafi
                wrote on 16 Dec 2015, 15:44 last edited by
                #7
                 import QtQuick 2.3
                 import QtQuick.Window 2.2
                 
                 Window {
                     visible: true
                     width: 600
                     height: 360
                     property var someObject : makeSomeObject("SomeTitle")
                     function  makeSomeObject(title){
                         var obj = {
                                 title:  title,
                                 title2: Qt.binding( function() {return "another title";} )
                             };
                             return obj;
                     }
                 
                     ListView {
                        anchors.fill: parent
                        model: ListModel {id: list_model}
                        delegate: Text {text: list_model.get(index).title2}
                     }
                 
                     Component.onCompleted: {
                         list_model.append(someObject)
                         list_model.append(someObject)
                     }
                 }
                

                Remote object sharing (OO RPC)
                http://forum.qt.io/topic/60680/remote-object-sharing-oo-rpc-solved

                Advanced, Powerful and easy to use ORM for Qt5
                https://forum.qt.io/topic/67417/advanced-powerful-and-easy-to-use-orm-for-qt5

                M 1 Reply Last reply 17 Dec 2015, 08:48
                0
                • H Hamed.Masafi
                  16 Dec 2015, 15:44
                   import QtQuick 2.3
                   import QtQuick.Window 2.2
                   
                   Window {
                       visible: true
                       width: 600
                       height: 360
                       property var someObject : makeSomeObject("SomeTitle")
                       function  makeSomeObject(title){
                           var obj = {
                                   title:  title,
                                   title2: Qt.binding( function() {return "another title";} )
                               };
                               return obj;
                       }
                   
                       ListView {
                          anchors.fill: parent
                          model: ListModel {id: list_model}
                          delegate: Text {text: list_model.get(index).title2}
                       }
                   
                       Component.onCompleted: {
                           list_model.append(someObject)
                           list_model.append(someObject)
                       }
                   }
                  
                  M Offline
                  M Offline
                  MarcVanDaele
                  wrote on 17 Dec 2015, 08:48 last edited by
                  #8

                  @Hamed.Masafi said:

                               title2: Qt.binding( function() {return "another title";} )
                  

                  Thanks for the suggestion but this doesn't seem to work (at least not on my side). Does this work in your environment?

                  1 Reply Last reply
                  0
                  • H Offline
                    H Offline
                    Hamed.Masafi
                    wrote on 17 Dec 2015, 14:30 last edited by
                    #9

                    Yes and No.
                    This is an example. Qt.binding method will bind a value (not a literal) to object.
                    Binding will not work on this case else "another title" act as object, function, variable, ...
                    for example:

                    title2: Qt.binding( function() {return another_object.title;} )
                    

                    will works fine.
                    Another solutions is that get title (if features change is not needed) and pass it to title2, like this:

                    var t2 = some_value_from_some_where;
                    ...
                    title2: t2
                    

                    Remote object sharing (OO RPC)
                    http://forum.qt.io/topic/60680/remote-object-sharing-oo-rpc-solved

                    Advanced, Powerful and easy to use ORM for Qt5
                    https://forum.qt.io/topic/67417/advanced-powerful-and-easy-to-use-orm-for-qt5

                    M 1 Reply Last reply 17 Dec 2015, 15:22
                    0
                    • H Hamed.Masafi
                      17 Dec 2015, 14:30

                      Yes and No.
                      This is an example. Qt.binding method will bind a value (not a literal) to object.
                      Binding will not work on this case else "another title" act as object, function, variable, ...
                      for example:

                      title2: Qt.binding( function() {return another_object.title;} )
                      

                      will works fine.
                      Another solutions is that get title (if features change is not needed) and pass it to title2, like this:

                      var t2 = some_value_from_some_where;
                      ...
                      title2: t2
                      
                      M Offline
                      M Offline
                      MarcVanDaele
                      wrote on 17 Dec 2015, 15:22 last edited by
                      #10

                      @Hamed.Masafi I see your point. However, the attempt below still fails.
                      The text in the Text element is shown correctly so there the title2() evaluates correctly (it also displays correctly when using a literal and/or when using no binding)
                      However, as the example below illustrates, when using the same objects through a model in ListView.delegate, I still get the same errors as reported initially.

                      Your second proposal indeed works (and is similar to the proposal of dheerendra above). However, this implies that the function gets evaluated for every item in the model while I would like to only evaluate the function for every visible item (=> when used in the delegate)

                      import QtQuick 2.3
                      import QtQuick.Window 2.2
                      
                      
                      Window {
                          visible: true
                          width: 600
                          height: 360
                          property var someObject : makeSomeObject("SomeTitle1")
                          function  makeSomeObject(title){
                      
                      
                              var obj = {
                                      title:  title,
                                      title2: Qt.binding (function() {return someObject.title})
                                  };
                                  return obj;
                          }
                      
                          Text{
                              anchors.fill: parent
                              text: someObject.title2()
                          }
                      
                          ListView {
                             anchors.fill: parent
                             model: ListModel {id: list_model}
                             delegate: Text {text: list_model.get(index).title2()}
                          }
                      
                          Component.onCompleted: {
                              list_model.append(makeSomeObject("SomeTitle2"))
                              list_model.append(makeSomeObject("SomeTitle3"))
                          }
                      }
                      
                      1 Reply Last reply
                      0

                      10/10

                      17 Dec 2015, 15:22

                      • Login

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