C
Qt Quick Ultralite painteditem Example
Demonstrates the use of PaintedItem in a Qt Quick Ultralite Application.
Overview
The painteditem example uses the PaintedItem Qml type to draw directly on the framebuffer. It displays an animation emulating oscillatory motion of a circular blob on a curved ramp.
The example uses the OscillatorPaintedItem class, which overrides the paint() method to draw a curved ramp and a circular blob. The paint() method is called on every update event on the angle property, which is updated every 100ms.

Target platforms
Project structure
The painteditem example consists of following files:
CMakeLists.txtoscillator.qmlmain_baremetal.cpposcPaintedItem.cpposcPaintedItem.h
The CMake project file contains the build script and the project configuration, and oscillator.qml defines the application's UI.
main_baremetal.cpp contains the main function to set up the application on baremetal platforms.
The oscPaintedItem.h and oscPaintedItem.cpp files contain definition for the OscillatorPaintedItem class, which is derived from the PaintedItemDelegate class.
CMake project file
# Copyright (C) 2026 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial
cmake_minimum_required(VERSION 3.21.1)
project(painteditem VERSION 0.0.1 LANGUAGES C CXX ASM)
find_package(QulApp)
if(QUL_PLATFORM MATCHES "autosar")
qul_add_library(painteditem)
else()
qul_add_executable(painteditem)
endif()
qul_add_qml_module(painteditem
URI PaintedItemApp
QML_FILES oscillator.qml
SOURCES
oscPaintedItem.cpp
oscPaintedItem.h
NO_SBOM
)
target_link_libraries(painteditem PRIVATE Qul::Controls)
if(QUL_PLATFORM MATCHES "^rh850" OR QUL_PLATFORM MATCHES "^tvii")
target_compile_definitions(painteditem PRIVATE NO_TOUCH)
endif()
app_target_setup_os(painteditem)
# FreeRTOS uses the generated entry point; every other OS has its own main().
if(QUL_OS STREQUAL "FreeRTOS")
app_target_default_entrypoint(painteditem oscillator MODULE PaintedItemApp)
else()
target_sources(painteditem PRIVATE main_baremetal.cpp)
endif()PaintedItem
The delegate_ property of the PaintedItem Qml type points to the OscillatorPaintedItem instance.
//PaintedItem Object PaintedItem { id: oscillator anchors.right: parent.right anchors.top: parent.top anchors.fill: parent delegate_: OscillatorPaintedItem { id: delegate angle: 0.0 initialAngle: 50 pivotLength: 50 onAngleChanged: { delegate.update() } } }
Text item
Initial angle and the fixed damping factor for the oscillations are displayed at the top-left corner.
Text { anchors.top: parent.top anchors.topMargin: 8 anchors.left: parent.left anchors.leftMargin: 8 text: "Angle: " + delegate.initialAngle + "\ndamping: " + app.dampingFactor font.pixelSize: 13 }
Replay button
When the oscillation angle reaches 0, the circular blob is at rest. On pressing the Replay button the animation starts again by setting the initialAngle back to maximum.
Button { id: replay //For platforms not supporting touch input, hide Replay button. visible: !root.automaticAnimation anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.verticalCenter height: 40 width: 70 font.pixelSize: 13 text: "Replay" background: Rectangle { color: replay.down ? "#A39D9C" : "#B8B3B2" radius: 8 } onClicked: { /*Setting the initialAngle property to maximum value disturbs the equilibrium and triggers the animation again.*/ delegate.initialAngle = 50 }
Animation timer
The animation is on the angle property, which is updated every 100ms. Each update to the angle property triggers the delegate update, which calls the paint() method of OscillatorPaintedItem.
Timer { running: root.automaticAnimation repeat: true interval: 8000 onTriggered: delegate.initialAngle = 50 }
Files:
Available under certain Qt licenses.
Find out more.