简体   繁体   中英

QML: Is there an opportunity to create ListModel using <for loop>, and then using loop index on calculating ListModel item coordinates?

I need to create many similar elements, that differ only by coordinates.

I learned how to create this one by one:

 Repeater {
            model: ListModel {
            
                ListElement { p:100; q:100; w:50; h:50; c:"red"; o:0 }
                ListElement { p:200; q:100; w:50; h:50; c:"red"; o:0 }
                ListElement { p:300; q:100; w:50; h:50; c:"red"; o:0 }
                ListElement { p:400; q:100; w:50; h:50; c:"red"; o:0 }
                ListElement { p:500; q:100; w:50; h:50; c:"red"; o:0 }
                        }
                        delegate: Rectangle {
                            x: p
                            y: q
                            width: w
                            height: h
                            color: c
                            rotation: o
                        }
                    }

I have now come to the conclusion that it would be convenient to do this with a simple for loop, using the loop index when calculating the coordinates:

 Repeater {
            model: ListModel {
            
              for ( var i = 1; i <= 5; i++ )
                {
                ListElement { p:100*i; q:100; w:50; h:50; c:"red"; o:0 }
                }
                        }
                        delegate: Rectangle {
                            x: p
                            y: q
                            width: w
                            height: h
                            color: c
                            rotation: o
                        }
                    }

Unfortunately, there is a problem with loop scope, and of course I don't even expect it will work in that shape... I am trying to show only my idea in the second code.

Is there an opportunity to create ListElements like this or am I confusing two different ways of item creating?

As mentioned above, before you start writing a program, you need to learn the basics. You can't mix QML and Javascript in this way. It also seems to me that ListElement is completely out of place here.

Here's how it can be rewritten:

Repeater {
    model: 5
    delegate: Rectangle {
        x: 100 * index
        y: 100
        width: 50
        height: 50
        color: "red"
        rotation: 0
    }
}

If you need more control over the data, you can change to this:

Repeater {
    model: [1, 2, 3, 4, 5]
    delegate: Rectangle {
        x: 100 * modelData
        ...
    }
}

For your example, I highly recommend @folibis answer as that demonstrates the usage of index and modelData which both are most appropriate for your scenario.

Generally speaking, you can mix QML/Javascript, you just need more practice in knowing the correct syntax/context where you can use QML and where you can use Javascript. Also, there are legimite scenarios where you want to populate a ListModel programmatically.

In the following demo, a ListModel is populated programmatically in JavaScript imperatively. In fact, it is even executed after all the QML components are initialized, so, the Repeater actually initially sees an empty ListModel . Whilst executing the populate function, each append signals changes to the ListModel which your Repeater will acknowledge through incremental updates.

import QtQuick
import QtQuick.Controls
Page {
    Repeater {
        model: listModel
        delegate: Rectangle {
            x: p
            y: q
            width: w
            height: h
            color: c
            rotation: o
        }
    }
    ListModel {
        id: listModel
        function populate() {
            for ( let i = 1; i <= 5; i++ )
            {
                listModel.append( { p:100*i, q:100, w:50, h:50, c:"red", o:0 } );
            }
        }
    }
    Component.onCompleted: listModel.populate()
}

You can Try it Online!

Some time ago, when I was playing around with QML with the kids, we mocked up a "Click Invaders" game. The game has the following features:

  • ListModel will contain the position of the invaders
  • Repeater is used to render the invaders
  • Timer object is used to guarantee to make 10 invaders slowly appear on the screen
  • When the user clicks, the invader will "die" and be removed - this will trigger more invaders to spawn

Check it out. It has some concepts such as using SVG to render the graphic. It dynamically creates and destroys objects in different positions and orientations:

https://github.com/stephenquan/qmlonline6/wiki/Example-Click-Invaders

A very important section of the documentation to start with when coming to Qt Quick without JavaScript knowledge:

https://doc.qt.io/qt-6/qtqml-javascript-expressions.html

It's a must-see here if you didn't expect that you'll need to learn something besides C++ along with Qt.

The JavaScript environment provided by QML is stricter than that in a web browser. For example, in QML you cannot add to, or modify, members of the JavaScript global object. In regular JavaScript, it is possible to do this accidentally by using a variable without declaring it. In QML this will throw an exception, so all local variables must be explicitly declared. See JavaScript Environment Restrictions for a complete description of the restrictions on JavaScript code executed from QML.

Various parts of QML documents can contain JavaScript code:

The body of property bindings. These JavaScript expressions describe relationships between QML object properties. When dependencies of a property change, the property is automatically updated too, according to the specified relationship. The body of Signal handlers. These JavaScript statements are automatically evaluated whenever a QML object emits the associated signal. The definition of custom methods. JavaScript functions that are defined within the body of a QML object become methods of that object. Standalone JavaScript resource (.js) files. These files are actually separate from QML documents, but they can be imported into QML documents. Functions and variables that are defined within the imported files can be used in property bindings, signal handlers, and custom methods.

Should carefully distinguish between JavaScript and QML elements in Qt Quick. If QML is a language for creating a GUI, its elements are the types described in doc.qt.io. On the other hand, loops, variable definitions, arrays, etc. are JavaScript elements. It's not so obvious at first. By the way, this is a very good lesson if someone did not program in JS, only in C ++. The closeness of the syntax of the two languages may be surprising.

The documentation section above explains these dependencies

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM