Nova Flow OS
Qt6 QML Book
Qt6 QML Book
  • Qt6 QML Book
    • Preface
      • Welcome!
      • Acknowledgements
      • Authors
    • Meet Qt
      • Qt and Qt Quick
      • Qt Building Blocks
      • Qt 6 Introduction
    • Getting Started
      • Quick Start
      • Installing Qt 6 SDK
      • Hello World
      • Application Types
      • Summary
    • Qt Creator IDE
      • Qt Creator IDE
      • The User Interface
      • Registering your Qt Kit
      • Managing Projects
      • Using the Editor
      • Locator
      • Debugging
      • Shortcuts
    • Quick Starter
      • Quick Starter
      • QML Syntax
      • Core Elements
      • Components
      • Simple Transformations
      • Positioning Elements
      • Layout Items
      • Input Elements
      • Advanced Techniques
    • Fluid Elements
      • Fluid Elements
      • Animations
      • States and Transitions
      • Advanced Techniques
    • Qt Quick Controls
      • UI Controls
      • Introduction to Controls
      • An Image Viewer
      • Common Patterns
      • The Imagine Style
      • Summary
    • Model View
      • Model View-Delegate
      • Concept
      • Basic Models
      • Dynamic Views
      • Delegate
      • Advanced Techniques
      • Summary
    • Canvas
      • Canvas Element
      • Convenience API
      • Gradients
      • Shadows
      • Images
      • Transformation
      • Composition Modes
      • Pixel Buffers
      • Canvas Paint
      • Porting from HTML5 Canvas
    • Shapes
      • Shapes
      • A Basic Shape
      • Building Paths
      • Filling Shapes
      • Animating Shapes
      • Summary
    • Effects
      • Effects in QML
      • Particle Concept
      • Simple Simulation
      • Particle Parameters
      • Directed Particles
      • Affecting Particles
      • Particle Groups
      • Particle Painters
      • Graphics Shaders
      • Shader Elements
      • Fragment Shaders
      • Wave Effect
      • Vertex Shader
      • Curtain Effect
      • Summary
    • Multimedia
      • Multimedia
      • Playing Media
      • Sound Effects
      • Video Streams
      • Capturing Images
      • Summary
    • Qt Quick 3D
      • Qt Quick 3D
      • The Basics
      • Working with Assets
      • Materials and Light
      • Animations
      • Mixing 2D and 3D Contents
      • Summary
    • Networking
      • Networking
      • Serving UI via HTTP
      • Templates
      • HTTP Requests
      • Local files
      • REST API
      • Authentication using OAuth
      • Web Sockets
      • Summary
    • Storage
      • Storage
      • Settings
      • Local Storage - SQL
    • Dynamic QML
      • Dynamic QML
      • Loading Components Dynamically
      • Creating and Destroying Objects
      • Tracking Dynamic Objects
      • Summary
    • Javascript
      • JavaScript
      • Browser/HTML vs Qt Quick/QML
      • JS Language
      • JS Objects
      • Creating a JS Console
    • Qt C++
      • Qt and C++
      • A Boilerplate Application
      • The QObject
      • Build Systems
      • Common Qt Classes
      • Models in C++
    • Extending QML
      • Extending QML with C++
      • Understanding the QML Run-time
      • Plugin Content
      • Creating the plugin
      • FileIO Implementation
      • Using FileIO
      • Summary
    • Qt for Python
      • Qt for Python
      • Introduction
      • Installing
      • Building an Application
      • Limitations
      • Summary
    • Qt for MCUs
      • Qt for MCUs
      • Setup
      • Hello World - for MCUs
      • Integrating with C++
      • Working with Models
      • Summary
    • About
      • Readme
      • License
Powered by GitBook
On this page
  1. Qt6 QML Book
  2. Dynamic QML

Tracking Dynamic Objects

Working with dynamic objects, it is often necessary to track the created objects. Another common feature is to be able to store and restore the state of the dynamic objects. Both these tasks are easily handled using an XmlListModel that is dynamically populated.

In the example shown below two types of elements, rockets and ufos can be created and moved around by the user. In order to be able to manipulate the entire scene of dynamically created elements, we use a model to track the items.

The model, a XmlListModel, is populated as the items are created. The object reference is tracked alongside the source URL used when instantiating it. The latter is not strictly needed for tracking the objects but will come in handy later.

import QtQuick
import "create-object.js" as CreateObject

Item {
    id: root

    ListModel {
        id: objectsModel
    }

    function addUfo() {
        CreateObject.create("ufo.qml", root, itemAdded)
    }

    function addRocket() {
        CreateObject.create("rocket.qml", root, itemAdded)
    }

    function itemAdded(obj, source) {
        objectsModel.append({"obj": obj, "source": source})
    }

As you can tell from the example above, the create-object.js is a more generalized form of the JavaScript introduced earlier. The create method uses three arguments: a source URL, a root element, and a callback to invoke when finished. The callback gets called with two arguments: a reference to the newly created object and the source URL used.

This means that each time addUfo or addRocket functions are called, the itemAdded function will be called when the new object has been created. The latter will append the object reference and source URL to the objectsModel model.

The objectsModel can be used in many ways. In the example in question, the clearItems function relies on it. This function demonstrates two things. First, how to iterate over the model and perform a task, i.e. calling the destroy function for each item to remove it. Secondly, it highlights the fact that the model is not updated as objects are destroyed. Instead of removing the model item connected to the object in question, the obj property of that model item is set to null. To remedy this, the code explicitly has to clear the model item as the objects are removed.

function clearItems() {
    while(objectsModel.count > 0) {
        objectsModel.get(0).obj.destroy()
        objectsModel.remove(0)
    }
}

Having a model representing all dynamically created items, it is easy to create a function that serializes the items. In the example code, the serialized information consists of the source URL of each object along its x and y properties. These are the properties that can be altered by the user. The information is used to build an XML document string.

function serialize() {
    var res = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<scene>\n"

    for(var ii=0; ii < objectsModel.count; ++ii) {
        var i = objectsModel.get(ii)
        res += "  <item>\n    <source>" + i.source + "</source>\n    <x>" + i.obj.x + "</x>\n    <y>" + i.obj.y + "</y>\n  </item>\n"
    }

    res += "</scene>"

    return res
}

Currently, the XmlListModel of Qt 6 lacks the xml property and get() function needed to make serialization and deserialization work.

The XML document string can be used with an XmlListModel by setting the xml property of the model. In the code below, the model is shown along the deserialize function. The deserialize function kickstarts the deserialization by setting the dsIndex to refer to the first item of the model and then invoking the creation of that item. The callback, dsItemAdded then sets that x and y properties of the newly created object. It then updates the index and creates the next object, if any.

XmlListModel {
    id: xmlModel
    query: "/scene/item"
    XmlListModelRole { name: "source"; elementName: "source" }
    XmlListModelRole { name: "x"; elementName: "x" }
    XmlListModelRole { name: "y"; elementName: "y" }
}

function deserialize() {
    dsIndex = 0
    CreateObject.create(xmlModel.get(dsIndex).source, root, dsItemAdded)
}

function dsItemAdded(obj, source) {
    itemAdded(obj, source)
    obj.x = xmlModel.get(dsIndex).x
    obj.y = xmlModel.get(dsIndex).y

    dsIndex++

    if (dsIndex < xmlModel.count) {
        CreateObject.create(xmlModel.get(dsIndex).source, root, dsItemAdded)
    }
}

property int dsIndex

The example demonstrates how a model can be used to track created items, and how easy it is to serialize and deserialize such information. This can be used to store a dynamically populated scene such as a set of widgets. In the example, a model was used to track each item.

An alternate solution would be to use the children property of the root of a scene to track items. This, however, requires the items themselves to know the source URL to use to re-create them. It also requires us to implement a way to be able to tell dynamically created items apart from the items that are a part of the original scene, so that we can avoid attempting to serialize and later deserialize any of the original items.

PreviousCreating and Destroying ObjectsNextSummary

Last updated 9 months ago