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. Storing a function in a js object
Forum Updated to NodeBB v4.3 + New Features

Storing a function in a js object

Scheduled Pinned Locked Moved Solved QML and Qt Quick
3 Posts 2 Posters 296 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.
  • I Offline
    I Offline
    Idodoqdo
    wrote on last edited by
    #1

    Hello, I want to create a GridView that will contain different elements: Button, Text, Switch. I know that it is possible to use Delegate Chooser for this. The problem arises at the stage of creating a model that will store fields for the appropriate display (I will add the type field later). Now I'm faced with adding the nit300.focus is not allowed in the ListModel, so I decided to use the js model. I'm trying to store the function I'm going to call in it, but I get the following error

    TypeError: Property 'onClicked' of object [object Object] is not a function

    Code:

        GridView {
            id:grid
            anchors.fill: parent
    
            model: [
                {name: "Фокус Far", onClicked: function() {}}, // todo
                {name: "Фокус Near", onClicked: function() {print("near")}}, // todo
                {name: "Автофокус"},
                {name: "f ' = " + nit300.focus/100.0 + " mm"},
                {name: "Зум+"},
                {name: "Зум-"},
                {name: "E-Zoom 2X"},
                {name: "FoV"},
                {name: "Время интегрирования+"},
                {name: "Время интегрирования-"},
                {name: "Коррекция"},
                {name: "Зум не норма"},
                {name: "Яркость+"},
                {name: "Яркость-"},
                {name: "Manual BrightContrast"},
                {name: "Фокус не норма"},
                {name: "Контраст+"},
                {name: "Контраст-"},
                {name: "Positive/Negative"},
                {name: "Кулер не норма"},
                {name: "DDE--"},
                {name: "DDE++"},
                {name: "Self Check"},
                {name: "Температура не норма"},
                {name: "Ошибка связи"},
                {name: "ИК не норма"},
                {name: "Тестовый кадр"},
                {name: "Self Check Fail"},
            ]
    
            cellHeight: height / 7
            cellWidth: width / 4
    
            delegate:
                MyButton2 {
                width: grid.cellWidth
                height: grid.cellHeight
                text: modelData.name
                onClicked: {
                    if (modelData.onClicked !== null) {
                        modelData.onClicked()
                    }
                }
            }
        }
    

    I know that the following method may work

    property var actions: {"Фокус Near" : [function () {print("near";} ...}
    

    The model in C++ that I use is large and is not a QAbstractListModel, so I do it in qml. Tell me what is the best way to act in such cases

    B 1 Reply Last reply
    0
    • I Idodoqdo

      Hello, I want to create a GridView that will contain different elements: Button, Text, Switch. I know that it is possible to use Delegate Chooser for this. The problem arises at the stage of creating a model that will store fields for the appropriate display (I will add the type field later). Now I'm faced with adding the nit300.focus is not allowed in the ListModel, so I decided to use the js model. I'm trying to store the function I'm going to call in it, but I get the following error

      TypeError: Property 'onClicked' of object [object Object] is not a function

      Code:

          GridView {
              id:grid
              anchors.fill: parent
      
              model: [
                  {name: "Фокус Far", onClicked: function() {}}, // todo
                  {name: "Фокус Near", onClicked: function() {print("near")}}, // todo
                  {name: "Автофокус"},
                  {name: "f ' = " + nit300.focus/100.0 + " mm"},
                  {name: "Зум+"},
                  {name: "Зум-"},
                  {name: "E-Zoom 2X"},
                  {name: "FoV"},
                  {name: "Время интегрирования+"},
                  {name: "Время интегрирования-"},
                  {name: "Коррекция"},
                  {name: "Зум не норма"},
                  {name: "Яркость+"},
                  {name: "Яркость-"},
                  {name: "Manual BrightContrast"},
                  {name: "Фокус не норма"},
                  {name: "Контраст+"},
                  {name: "Контраст-"},
                  {name: "Positive/Negative"},
                  {name: "Кулер не норма"},
                  {name: "DDE--"},
                  {name: "DDE++"},
                  {name: "Self Check"},
                  {name: "Температура не норма"},
                  {name: "Ошибка связи"},
                  {name: "ИК не норма"},
                  {name: "Тестовый кадр"},
                  {name: "Self Check Fail"},
              ]
      
              cellHeight: height / 7
              cellWidth: width / 4
      
              delegate:
                  MyButton2 {
                  width: grid.cellWidth
                  height: grid.cellHeight
                  text: modelData.name
                  onClicked: {
                      if (modelData.onClicked !== null) {
                          modelData.onClicked()
                      }
                  }
              }
          }
      

      I know that the following method may work

      property var actions: {"Фокус Near" : [function () {print("near";} ...}
      

      The model in C++ that I use is large and is not a QAbstractListModel, so I do it in qml. Tell me what is the best way to act in such cases

      B Offline
      B Offline
      Bob64
      wrote on last edited by Bob64
      #2

      @Idodoqdo when I did something similar, I used a ListModel that I initialised from a js array:

      ListModel {
          id: myModel
          readonly property modelItems:  [
              { name: "bob", onClicked: function() {console.log("Hello")} },
              ...
          ]
          function init() {
                  modelItems.forEach(function(item) {
                      myModel.append(item)
                  });
          }
      }
      

      You can call init() in a Component.onCompleted of your containing component.

      Then in the delegate, I do something like this:

      delegate:
          MyButton {
              ...
              onClicked: myModel.modelItems[index].onClicked()
          }
      

      The basic issue I was working around was that it wasn't possible to store (in such a way that it can be accessed and used) a function in the model. The idea is to have the model definition data outside of the model, to initialise the model from the data, but for function fields just to use the current index in the delegate to refer back to the original data to obtain the function.

      I think this works if the model is static. It would probably get trickier if the model needs to be more dynamic. There might be a better approach but this has been working for me.

      I 1 Reply Last reply
      0
      • B Bob64

        @Idodoqdo when I did something similar, I used a ListModel that I initialised from a js array:

        ListModel {
            id: myModel
            readonly property modelItems:  [
                { name: "bob", onClicked: function() {console.log("Hello")} },
                ...
            ]
            function init() {
                    modelItems.forEach(function(item) {
                        myModel.append(item)
                    });
            }
        }
        

        You can call init() in a Component.onCompleted of your containing component.

        Then in the delegate, I do something like this:

        delegate:
            MyButton {
                ...
                onClicked: myModel.modelItems[index].onClicked()
            }
        

        The basic issue I was working around was that it wasn't possible to store (in such a way that it can be accessed and used) a function in the model. The idea is to have the model definition data outside of the model, to initialise the model from the data, but for function fields just to use the current index in the delegate to refer back to the original data to obtain the function.

        I think this works if the model is static. It would probably get trickier if the model needs to be more dynamic. There might be a better approach but this has been working for me.

        I Offline
        I Offline
        Idodoqdo
        wrote on last edited by
        #3

        @Bob64
        Thanks I was doing something like this

            ListModel {
                id: buttonsModel
        
                property var actions: {
                    "Config" : [function () {gcpp.openConfFile();}, null, null], // clicked, pressed, released
                    "Wide" : [null, function() {bhz.setContZoom(-1);}, function() {bhz.setContZoom(0);}],
                    "Tele" : [null, function() {bhz.setContZoom(1);}, function() {bhz.setContZoom(0);}],
                    "Near" : [null, function() {bhz.setContFocus(-1);}, function() {bhz.setContFocus(0);}],
                    "Far" : [null, function () {bhz.setContFocus(1)}, function () {bhz.setContFocus(0)}],
                    "Open" : [null, function() {bhz.setContIris(1)}, function() {bhz.setContIris(0)}],
                    "Close" : [null, function() {bhz.setContIris(-1)}, function() {bhz.setContIris(0)}],
                }
        
                ListElement {
                    name: "Config"
                }
        
                ListElement {
                    name: ""
                }
        
                ListElement {
                    name: "Wide"
                }
        
                ListElement {
                    name: "Tele"
                }
                ListElement {
                    name: "Near"
                }
                ListElement {
                    name: "Far"
                }
                ListElement {
                    name: "Open"
                }
                ListElement {
                    name: "Close"
                }
            }
        

        I thought there was a more concise way.

        1 Reply Last reply
        0
        • I Idodoqdo has marked this topic as solved on

        • Login

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