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

Making repeating code generic



  • So I have come up with a plan for how I want to implement my keypad. In total the code will looking something similar to this (haven't refined the idea yet):

    Rectangle
    {
      id: rect
      anchors.verticalCenter: parent.verticalCenter
      width: parent.width - 100
      height: parent.height
      anchors.centerIn: parent
      color: "white"
      radius: 5
    
      QtObject
      {
        id: modelData
    
        property var label: "The Label"
        property var unit: "The Unit"
    
        property int minValue: 0
        property int maxValue: 100
        property int value: 100
      }
    
      Text
      {
        id: numericEntryDisplay
        elide: Text.ElideRight
        width: parent.width
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: parent.bottom
        horizontalAlignment: Text.AlignHCenter
        text: modelData.value
      }
    
      Text
      {
        id: unitText
        text: modelData.unit
        anchors.left: parent.right
        anchors.bottom: parent.bottom
      }
    
      MouseArea
      {
        anchors.fill: parent
        onClicked: showNumericKeyboard("systemDialog", 
                                       [qsTr("Cancel"), qsTr("Finished")], 
                                       1, modelData, qsTr(""), 0);
      }
    }
    

    The problem is that I am going to have instantiate this code 3 or 4 times per page. So I am looking to make it more generic. Perhaps make it it's own component? In general, what would the process of making this generic look like?

    For instance, I would love it if I could just call it something like KeypadRect and whenever I call that I could specify a few things... for example in my mind it would look something like:

    KeypadRect
    {
      id: inputX
      anchors
      {
        //some anchoring bindings
      }
      model: 
      {
        value: x
        unit: "x"
        minValue: y
        etc...
      }
    }
    

    Would I need to wrap it in Item to do this or what's the Qt standard for doing something like this?


  • Moderators

    @Circuits said in Making repeating code generic:

    Would I need to wrap it in Item to do this or what's the Qt standard for doing something like this?

    • Your top-level Rectangle is enough
    • Add a property for your model, to expose it to the outside world
    • Move your code to a new QML file and remember to start file name with Capital letter (otherwise QML engine won't see it)
    • Then you can start using that component in your other QML files (if it's in different directory, use import statement)


  • @sierdzio "Add a property to your model, to expose it to the outside world."

    Could you elaborate a bit on this? What would this property be? Do you mean:

    property (x) myModel: QtObject
      {
        id: modelData
    
        property var label
        property var unit
    
        property int minValue
        property int maxValue
        property int value
      }
    

  • Moderators

    I meant the rectangle. Only top-level properties are visible to the outside (to other QML files). It can even be something as simple as:

    Rectangle {
      property alias model: modelData
    }
    


  • @sierdzio Perhaps I am not allowed to do what I am trying to do. I will post the code so you know what's going on:

    //main.qml
    import QtQuick 2.12
    import QtQuick.Window 2.12
    
    Window {
        id: _theWindow
        visible: true
        width: 640
        height: 480
    
        function showComponent(settingValue)
        {
            var comp = Qt.createComponent("qrc:/theObjectToCreate.qml");
            comp.createObject(_theWindow,{"settingValue": settingValue})
        }
    
        RectComp {
            id: _theRectangleComponent
            property alias theAlias: _theRectangleComponent
            theAlias.myObject.mainValue: 5
        }
    }
    
    //RectComp.qml
    import QtQuick 2.12
    import QtQuick.Window 2.12
    
    Rectangle
    {
        id: _theRectangle
        width: 100
        height: 100
        anchors.centerIn: parent
        color: "lightblue"
    
        property alias myObject: _theObject
    
        QtObject
        {
            id: _theObject
            property int mainValue
        }
        
        MouseArea
        {
            anchors.fill: parent
            onClicked: showComponent(_theObject);
        }
    }
    
    //theObjectToCreate.qml
    import QtQuick 2.12
    import QtQuick.Window 2.12
    
    Window {
        id: _newWindow
        visible: true
        width: 640
        height: 480
    
        property QtObject settingValue
    
        Rectangle
        {
            id: _newRectangle
            width: 100
            height: 100
            color: "gray"
            anchors.centerIn: parent
    
            Text
            {
                id: _displayText
                anchors.centerIn: parent
                text: settingValue.mainValue
            }
        }
    }
    

    As you can see I am attempting to create a Component on a click. The Component will then display the values passed to it from the QtObject and I would like to set that QtObject's properties from within main. However, the second rectangle is displaying 0 when I am expecting it to display 5.

    EDIT:

    So I figured out that I can set the value if I do something like this:

    RectComp {
            id: _theRectangleComponent
            property alias theAlias: _theRectangleComponent
            Component.onCompleted: theAlias.myObject.mainValue = 5
        }
    

    but I was hoping I could just set the _theObject's property values from within main as though they were _theRectangleComponent's own properties. Perhaps that just isn't possible?


  • Moderators

    @Circuits said in Making repeating code generic:

    property alias theAlias: _theRectangleComponent

    This line is completely unnecessary.

    theAlias.theModel.mainValue: 5

    This should be:

    theModel.mainValue: 5
    


  • @sierdzio That's how I figured it should work but it doesn't seem to like the QtObject property. For instance, if I setup two property's inside of RectComp.qml like so:

    //RectComp.qml
    ...
    Rectangle
    {
        id: _theRectangle
        ...
        property alias myObject: _theObject
        property string genericString
    
        QtObject
        {
            id: _theObject
            property int mainValue
        }
        ...
    

    and I then try to assign values to them in main:

    genericString: "generic"
    myObject.mainValue: 5
    

    There is no trouble with genericString but I get an error on myObject.mainValue: 5:

    Cannot assign to non-existent property "mainValue"

    However, if I instead assign it a value in main like so:

    Component.onCompleted:
    {
      myObject.mainValue = 5
    }
    

    then it works.



  • @Circuits Fixed by making the QtObject an internal component of _theRectangle like so:

    //RectComp.qml
    import QtQuick 2.12
    import QtQuick.Window 2.12
    
    Rectangle
    {
        id: _theRectangle
        width: 100
        height: 100
        anchors.centerIn: parent
        color: "lightblue"
    
        property alias myObject: _theObject
    
        InternalObjectComp
        {
            id: _theObject
        }
        
        MouseArea
        {
            anchors.fill: parent
            onClicked: showComponent(_theObject);
        }
    }
    

Log in to reply