Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How do QML objects pass in function parameters?



  • Item{
        id:root
        property string btnTest:""
       void setPos(Button curBtn)
       {
            btnTest = curBtn.text
       }
        Button{
            id:btn
            text:"TEST"
        }
    }
    

  • Qt Champions 2018

    @lawrence-emke said in How do QML objects pass in function parameters?:

    @Allon You should not pass QML objects as arguments in a function call.
    All function calls are a "pass by value". This means that a "copy"
    of your object is passed to your function (objects are not small things and have a lot of pointers). The copied object is not the real object.
    Any changes you make will be to the copied object.

    That is incorrect, you can pass QML objects as arguments to a function, and they aren't passed as value if they are QObjects, but as pointers. Plain JS objects do get passed as value though.

    If you want to pass an object to a function you need to pass a
    "pseudo value" which can be used as an identifier to locate the real object.
    So here is the process:
    Locate the object you want to pass.
    The "id" values do not exist at run time. You can not use it.

    You can use id at runtime, it's not a property but it can be used to identify an object.

    Item {
        id: foo
    }
    Item {
        id: bar
        function func(item) { ... }
    }
    
    // calling bar.func(foo) works and bar can modify foo in func
    

    If you can do something else, don't rely on objectName to identify an object.

    As for @Allon 's actual problem, it is just a syntactic error.

    Instead of

               function setRect(Object obj) { 
                     anchors.fill: obj
               }  
    

    You should have

               function setRect(obj) { 
                     anchors.fill = obj;
               }  
    

    That code is correct but doesn't like good practice QML, too imperative. I would advice you to rethink what you are doing.



  • Hi,
    You usually do not as you can access elements properties directly. Here is an example where I get the button text directly from the button text property without using paramaters:

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Controls 2.12
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
    
        function showButtonText() {
            console.log("My button text: " + btn.text )
        }
    
        Button{
            id:btn
    
            text: "TEST"
    
            MouseArea {
                id: buttonMousearea
    
                anchors.fill: parent
    
                onClicked: {
                    showButtonText()
                }
            }
        }
    }
    


  • @Allon Hello, if I have to pass in QML object to a function argument, what do I do?



  • @mirro What do you mean by passing in QML object to a function. Can you tell me what it could be used to?
    I did not understood your example.



  • @Allon I want to implement the following code,but this setRect(Object obj) syntax error.

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Controls 2.12
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
       Rectangle{
               id:rct
               color: "red"
               function setRect(Object obj) { 
                     anchors.fill: obj
               }  
       }
    
    
        Button{
            id:btn
    
            text: "TEST"
    
            MouseArea {
                id: buttonMousearea
    
                anchors.fill: parent
    
                onClicked: {
                     rct.setRect(btn)
                }
            }
        }
    
          Button{
            id:btn2
    
            text: "TEST2"
    
            MouseArea {
                id: buttonMousearea
    
                anchors.fill: parent
    
                onClicked: {
                        rct.setRect(btn2)
                }
            }
        }
    }
    


  • @Allon You should not pass QML objects as arguments in a function call.

    You have to understand what is happening behind the curtain.
    All function calls are a "pass by value". This means that a "copy"
    of your object is passed to your function (objects are not small things and have a lot of pointers). The copied object is not the real object.
    Any changes you make will be to the copied object.

    If you want to pass an object to a function you need to pass a
    "pseudo value" which can be used as an identifier to locate the real object.

    So here is the process:
    Locate the object you want to pass.

    The "id" values do not exist at run time. You can not use it.

    So you need a property that DOES exist at run time. Qt has defined the "objectName" attribute to all "normal" objects. Its default value is the empty string. You can set it to any value you want. You can use this value to allow the called function to locate your object. You can pass it to any function because it is only a string. You can even change it at execution time.

    Have the called function use this value to locate the real object.

    Be aware: The objectName is a "string" there is no guarantee that it is unique. If you create your own object (a separate qml file). In that file you set the objectName value (and don't change it) then all instances of the object will have the same objectName value. You have to come up with the method to identify multiple occurrences. Or you should make it clear that this is an assumption that your application is dependent on.

    Hope this helps


  • Qt Champions 2018

    @lawrence-emke said in How do QML objects pass in function parameters?:

    @Allon You should not pass QML objects as arguments in a function call.
    All function calls are a "pass by value". This means that a "copy"
    of your object is passed to your function (objects are not small things and have a lot of pointers). The copied object is not the real object.
    Any changes you make will be to the copied object.

    That is incorrect, you can pass QML objects as arguments to a function, and they aren't passed as value if they are QObjects, but as pointers. Plain JS objects do get passed as value though.

    If you want to pass an object to a function you need to pass a
    "pseudo value" which can be used as an identifier to locate the real object.
    So here is the process:
    Locate the object you want to pass.
    The "id" values do not exist at run time. You can not use it.

    You can use id at runtime, it's not a property but it can be used to identify an object.

    Item {
        id: foo
    }
    Item {
        id: bar
        function func(item) { ... }
    }
    
    // calling bar.func(foo) works and bar can modify foo in func
    

    If you can do something else, don't rely on objectName to identify an object.

    As for @Allon 's actual problem, it is just a syntactic error.

    Instead of

               function setRect(Object obj) { 
                     anchors.fill: obj
               }  
    

    You should have

               function setRect(obj) { 
                     anchors.fill = obj;
               }  
    

    That code is correct but doesn't like good practice QML, too imperative. I would advice you to rethink what you are doing.



  • @GrecKo I do not have any problem. This is mirro's one :) I just tryed to help.



  • @mirro I stand corrected. My question is how does the QML engine know when to pass by reference and when to pass by value, since the syntax is the same? Are only the basic data types passed by value, and everything else is passed by reference? I thought I read in the documentation somewhere that it was not a good idea. I guess that has changed. Is there some documentation that I can read that explains this? Please let me know. I want to learn.



  • @lawrence-emke
    I just found the following documentation:

    The QML engine has the ability to introspect QObject instances through the meta-object system. This means any QML code can access the following members of an instance of a QObject-derived class:

    Properties
    Methods (providing they are public slots or flagged with Q_INVOKABLE)
    Signals
    (Additionally, enums are available if they have been declared with Q_ENUMS. See Data Type Conversion Between QML and C++ for more details.)

    In general, these are accessible from QML regardless of whether a QObject-derived class has been registered with the QML type system. However, if a class is to be used in a way that requires the engine to access additional type information — for example, if the class itself is to be used as a method parameter or property, or if one of its enum types is to be used in this way — then the class may need to be registered.

    Also note that a number of the important concepts covered in this document are demonstrated in the Writing QML Extensions with C++ tutorial.

    Data Type Handling and Ownership
    Any data that is transferred from C++ to QML, whether as a property value, a method parameter or return value, or a signal parameter value, must be of a type that is supported by the QML engine.

    By default, the engine supports a number of Qt C++ types and can automatically convert them as appropriately when used from QML. Additionally, C++ classes that are registered with the QML type system can be used as data types, as can their enums if appropriately registered. See Data Type Conversion Between QML and C++ for further information.

    Additionally, data ownership rules are taken into consideration when data is transferred from C++ to QML. See Data Ownership for more details.

    I notice it says properties, methods and signals. It does not state QML objects. What does that mean? (an oversight?)



  • @lawrence-emke

    Certainly not all objects are passed by reference. If that was the case, then passing two variables to a function, depending on the way in which the function is written could modify one of the passed arguments unintentionally. It seems more reasonable to prevent unexpected changes to arguments of a function by using copied value.

    This is probably why most languages have some way of indicating an argument is passed by reference and not by value. Not only does it save copying, but makes the function writer aware that the changes made to the object are made directly to the object rather than a copy.


Log in to reply