SlideShare a Scribd company logo
© Integrated Computer Solutions, Inc. All Rights Reserved
Best Practices in Qt
Quick/QML Part 4
Justin Noel
Senior Consulting Engineer
ICS, Inc.
© Integrated Computer Solutions, Inc. All Rights Reserved
Agenda
• QML Data Models
• View Delegates
• Performance Tips
© Integrated Computer Solutions, Inc. All Rights Reserved
Data Models
© Integrated Computer Solutions, Inc. All Rights Reserved
Model – View – Delegate
Pattern
• Views in QML are Model-View-Delegate
• Model is an interface to data
• View manages item geometries
• Delegate implements item UI
• Drawing graphics
• Editing data
© Integrated Computer Solutions, Inc. All Rights Reserved
Models in QML
• All models are lists in QML
• No tables
• Can be implemented using roles
• No trees
• Can be implemented using
QSortFilterProxyModel
© Integrated Computer Solutions, Inc. All Rights Reserved
Model Roles
• Roles are like a “3rd Dimension” to cells
• Can be use to apply extra attributes
• Visible and non-visible
• These roles in basic QML are used to make
complex cells
• Can be used to emulate a table
© Integrated Computer Solutions, Inc. All Rights Reserved
Model Roles
• Consider this ContactsListModel
• One item in the list can be very complex
Name Role
Phone Number Role
Address Role
Image Role
Justin Noel
230 Second Ave
Waltham, MA
(617 ) 621 - 0060
© Integrated Computer Solutions, Inc. All Rights Reserved
Model Types in QML
• QML ListModel Item
• QML list<> property
• JavaScript JSON
• QQmlListProperty<Type>
• QList<QObject*>
• QAbstractItemModel*
© Integrated Computer Solutions, Inc. All Rights Reserved
QML List Model
• ListModel is a list of ListElement Items
• ListElement is a list of Key/Value pairs
• Key names are arbitrary
• Use whatever is convenient
ListView {
model: contactModel
}
ListModel {
id: contactModel
ListElement { name: “Justin Noel”; phoneNumber: “(617) 621-0060” }
ListElement { name: “John Doe”; phoneNumber: “(555) 555-5555” }
}
© Integrated Computer Solutions, Inc. All Rights Reserved
Delegates
• Roles appear as attached properties in a Delegate
ListView {
model: contactModel
delegate: Rectangle {
Column {
Text { text: name }
Text { text: phoneNumber }
}
}
ListModel {
id: contactModel
ListElement { name: “Justin Noel”; phoneNumber: “(617) 621-0060” }
ListElement { name: “John Doe”; phoneNumber: “(555) 555-5555” }
}
© Integrated Computer Solutions, Inc. All Rights Reserved
QML Specialty Models
• XmlListModel
• Create a model from XML
• Using XPath and XQuery statements
• FolderListModel
• Lists a directory on the disk
• Not a tree
© Integrated Computer Solutions, Inc. All Rights Reserved
QML List Property Model
//ContactList.qml
Item {
property list<Contact> contactModel: undefined
ListView {
model: contactModel
delegate: Rectangle {
Column {
Text { text: name }
Text { text: phoneNumer }
}
}
}
//Main.qml
ContactList {
contactModel: [
Contact{ name: “Justin Noel”; phoneNumber: “(617) 621-0060” },
Contact{ name:” John Doe”; phoneNumber: “(555) 555-5555” }
]
}
© Integrated Computer Solutions, Inc. All Rights Reserved
JSON Model
Item {
property var json: [
{ name:”Justin Noel” phoneNumber:”(617) 621-0060” },
{ name:” John Doe” phoneNumber “(555) 555-5555” }
]
ListView {
model: json
delegate: Rectangle {
Column {
Text { text: name }
Text { text: phoneNumer }
}
}
}
© Integrated Computer Solutions, Inc. All Rights Reserved
QList<QObject*> Model
class Alarm : public QObject
{
Q_OBJECT
Q_PROPERTY(Severity severity...)
Q_PROPERTY(QString description...)
[...]
};
QML_DECLARE_METATYPE(Alarm*);
class CoffeeMaker : public QObject
{
Q_OBJECT
Q_PROPERTY(QList<Alarm*> alarms READ alarms NOTIFY alarmsChanged)
public:
QList<Alarm*> alarms() const
{
return m_alarms;
}
};
© Integrated Computer Solutions, Inc. All Rights Reserved
QList<QObject*> Model
import MrCoffee 1.0
Rectangle {
CoffeeMaker {
id: maker
}
ListView {
anchors.fill: parent
model: maker.alarms
}
}
© Integrated Computer Solutions, Inc. All Rights Reserved
QQmlListProperty
class BarChart : public QObject
{
Q_OBJECT
Q_CLASSINFO("DefaultProperty", “bars")
Q_PROPERTY(QQmlListProperty<Bar> bars READ bars NOTIFY
barsChanged)
public:
QQmlListProperty bars() const;
protected:
static int barCount(QQmlListProperty<Bar>* property);
static Axis* barAt(QQmlListProperty<Bar>* property, int index);
static void appendBar(QQmlListProperty<Bar>* property, Bar*
value);
static void clearBars(QQmlListProperty<Bar>* property);
private:
QList<Bar*> m_bars;
};
© Integrated Computer Solutions, Inc. All Rights Reserved
QQmlListProperty
QQmlListProperty BarChart::bars() const
{
return QQmlListProperty<Bar>(this, nullptr,
&BarChart::appendBar,
&BarChart::barCount,
&BarChart::barAt,
&BarChart::clearBars);
}
int BarChart::barCount(QQmlListProperty<Bar>* property)
{
BarChart* self = qobject_cast<BarChart*>(property->object);
return self->m_bars.count();
}
Bar* BarChart::barAt(QQmlListProperty<Bar>* property, int index)
{
BarChart* self = qobject_cast<BarChart*>(property->object);
return self->m_bars[index];
}
© Integrated Computer Solutions, Inc. All Rights Reserved
QQmlListProperty
void BarChart::appendBar(QQmlListProperty<Bar>* property, Bar*
value)
{
BarChart* self = qobject_cast<BarChart*>(property->object);
self->m_bars.append(value);
emit self->barsChanged();
}
void BarChart::clearBars(QQmlListProperty<Bar>* property)
{
BarChart* self = qobject_cast<BarChart*>(property->object);
self->m_bars.clear();
emit self->barsChanged();
}
© Integrated Computer Solutions, Inc. All Rights Reserved
QQmlListProperty
import BarChart 1.0
Rectangle {
BarChart {
Bar {
color: “red”
value: 50
}
Bar {
color: “blue”
value: 10
}
}
}
© Integrated Computer Solutions, Inc. All Rights Reserved
QAbstractItemModel
• Data model interface from Qt Interview Framework
• Originally designed for QWidgets
• QListView, QTableView, QTreeView
• QAbstractItemModel is a tree interface w/ roles
• Remember: QML Doesn’t support Tables or Trees
• Makes the interface a little confusing for those
not familiar with the QWidget views
© Integrated Computer Solutions, Inc. All Rights Reserved
QAbstractListModel
• QAbstractListModel is a specialized QAIM
• Implements some of the tree interface
• Makes it easier to implement a list
• Data models should wrap data rather than store data
• Simple interface
© Integrated Computer Solutions, Inc. All Rights Reserved
Alarm Model Implementation
class AlarmModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Roles { SeverityRole = Qt::UserRole,
DescriptionRole };
AlarmModel(DataModel& data);
QHash<int, QByteArray> roleNames() const;
int rowCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role) const;
private slots:
void handleAlarmAppened();
void handleAlarmRemoved(int alarm);
private:
DataModel& m_data;
};
© Integrated Computer Solutions, Inc. All Rights Reserved
Alarm Model Implementation
AlarmModel::AlarmModel(DataModel& data) :
m_data(data)
{
connect(&data, SINGAL(alarmsAppened()),
this, SLOT(handleAlarmAppened()));
connect(&data, SINGAL(alarmsRemoved(int)),
this, SLOT(handleAlarmRemoved(int)));
}
QHash<int, QByteArray> AlarmModel::roleNames() const
{
static QHash<int, QByteArray> roles;
if(roles.isEmpty) {
roles.insert(SeverityRole, “severity”);
roles.insert(DescriptionRole, “description”);
}
return roles;
}
© Integrated Computer Solutions, Inc. All Rights Reserved
Alarm Model Implementation
int AlarmModel::rowCount(const QModelIndex& parent) const
{
if(!parent.isValid())
return m_data.alarms().size();
else
return 0;
}
QVariant AlarmModel::data(const QModelIndex& index, int role) const
{
if(!index.isValid() || index.column() != 0)
return QVariant();
else if(role == SeverityRole)
return m_data.alarms()[index.row()].severity();
else if(role == DescriptionRole)
return m_data.alarms()[index.row()].description();
}
© Integrated Computer Solutions, Inc. All Rights Reserved
Alarm Model Implementation
void AlarmModel::handleAlarmAppened()
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
endInsertRows();
}
void AlarmModel::handleAlarmRemoved(int alarm)
{
beginRemoveRows(QModelIndex(), alarm, alarm);
endRemoveRows();
}
© Integrated Computer Solutions, Inc. All Rights Reserved
Which Model Is Right For Me?
• Use Case! Use Case! Use Case!
• Web Services based app
• Use JSON or XmlListModel
• C++ based app
• Use QAbstractItemModel or QList<QObject*>
• Composite QML items like BarChart
• Consists of N Bar items
• property list<Type>
© Integrated Computer Solutions, Inc. All Rights Reserved
Delegates
© Integrated Computer Solutions, Inc. All Rights Reserved
Delegate Performance Tips
• Keep it short. Keep it Simple
• Avoid Loader
• Avoid Shader Effects / Graphical Effects
• Avoid clip: true
• Increase cacheBuffer property for smoother scrolling
• At the cost of memory
© Integrated Computer Solutions, Inc. All Rights Reserved
Coupled Delegate/Model/View
• Avoid tight relationships between the view properties, model
roles and athedelegate
Item {
property var json: [
{ name:”Justin Noel” icon:”jn.png” },
{ name:” John Doe” icon: “jd.png” }
]
ListView {
model: json
delegate: Rectangle {
color: ListView.view.isCurrentItem ? “blue” : “white”
Column {
Image { source: icon }
Text { text: name }
}
MouseArea { onClicked: doSomething(index)}
}
}
© Integrated Computer Solutions, Inc. All Rights Reserved
New Delegate Item
• Create a new item for your Delegate
ContactRow.qml
------------------------------------------------------
Rectangle {
id: contactRow
property alias icon: icon.source
property alias text: name.text
property bool isSelected: false
signal clicked()
color: isSelected ? “blue” : “white”
Column {
Image { id: icon }
Text { id: text }
}
MouseArea {
onClicked: contactRow.clicked()
}
}
© Integrated Computer Solutions, Inc. All Rights Reserved
Delegate Abstraction
Item {
property var json: [
{ name:”Justin Noel” icon:”jn.png” },
{ name:” John Doe” icon: “jd.png” }
]
ListView {
model: json
delegate: ContactRow {
isSelected: ListView.view.isCurrentItem
text: modelData.name
icon: modelData.icon
onClicked: doSomething(index)
}
}
© Integrated Computer Solutions, Inc. All Rights Reserved
Performance Tips
© Integrated Computer Solutions, Inc. All Rights Reserved
Be Asynchronous
• Never spend more than a couple of milliseconds within
blocking functions
• 60Hz drawing leaves 16ms to get work done
• Or frames get dropped!
• User worker threads to do heavy lifting
• QThread or QML WorkerScript
• Never manually spin the event loop
• QCoreApplication::processEvents()
• This was sorta-kinda acceptable for with widgets
© Integrated Computer Solutions, Inc. All Rights Reserved
C++ Type Conversions
• Avoid variant type QML properties
• Marked as deprecated
• Use var instead
• Still try to use a specific type if you can
• Assigning list types can be expensive
• Optimizations implemented are made for
• QString, QUrl, int, bool, qreal, pointer types
© Integrated Computer Solutions, Inc. All Rights Reserved
Animations
• Animating properties will cause bindings to update
• Usually what is wanted
• If not use PropertyAction to “unbind” temporarily
• Or create a second animatedValue property
• See Bar Chart Example
© Integrated Computer Solutions, Inc. All Rights Reserved
Rendering Performance
• Avoid Clipping
• Very expensive
• Hide non-visible items (visible = false)
• Off screen items
• Completely obscured items
• QtQuick will call rendering methods for all visible
items
© Integrated Computer Solutions, Inc. All Rights Reserved
Startup Performance
• Load as little QML as possible at startup
• main.qml loads a splash screen
• main.qml uses async loader to show 1st screen
• Connect loader.progress to an indicator
• main.qml hides splash screen when
• loader.status === Loader.Ready
• From here load the screens as the user finds them
• Using Loader or component.createObject()
© Integrated Computer Solutions, Inc. All Rights Reserved
Runtime Performance
• Use lazy loading to load screens on demand
• Cache screens as they are found
• Or at least common screens
• Caching screens causes two side effects
• Increase in memory footprint
• Processing of bindings for items not on the
screen
© Integrated Computer Solutions, Inc. All Rights Reserved
Processing Bindings Off
Screen
• Bindings are re-calculated when property NOTIFY
signals are emitted
• On screen or not
• This might not be a bad thing
• If your system is mostly idle
• Might as well update bindings while system
is idle
• Rather than fetch all the data and re-calc
when switching screens which might be
animated
• Use case dependent. YMMV.
© Integrated Computer Solutions, Inc. All Rights Reserved
Memory Usage
• QML uses quite a bit of memory
• Typical app is around 10MB resident
• Qt internals is making this better
• Delete items made with Component createObject
• Use destroy()
• Delete uncommon dialogs after the user is done with
them
• Trading memory for screen reload performance
© Integrated Computer Solutions, Inc. All Rights Reserved
Processor Performance
• QtQuick 2 is OpenGL ES 2.0 based
• But some things still need to be run on the main
processor
• Animations @ 60 Hz require about 30% of the
lowend TI AM3358 CPU*
• Code from event handlers can only block for
16ms max
• Or frames will be dropped
• User will notice if it’s bad enough
© Integrated Computer Solutions, Inc. All Rights Reserved
Fake Animations
• If you just need small animated indicators and are very
short on processor power….
• Consider AnimatedImage
• Takes an animated GIF
• 15fps is around 5 percent CPU
• User won’t notice
© Integrated Computer Solutions, Inc. All Rights Reserved
Thank You!
Justin Noel
Senior Consulting Engineer
ICS, Inc.

More Related Content

PDF
Best Practices in Qt Quick/QML - Part 1 of 4
 
PDF
Lessons Learned from Building 100+ C++/Qt/QML Devices
 
PDF
In-Depth Model/View with QML
 
PPTX
Best Practices in Qt Quick/QML - Part I
 
PPTX
UI Programming with Qt-Quick and QML
PPTX
Qt Qml
PDF
Best Practices in Qt Quick/QML - Part II
 
PDF
Qt Application Programming with C++ - Part 1
Best Practices in Qt Quick/QML - Part 1 of 4
 
Lessons Learned from Building 100+ C++/Qt/QML Devices
 
In-Depth Model/View with QML
 
Best Practices in Qt Quick/QML - Part I
 
UI Programming with Qt-Quick and QML
Qt Qml
Best Practices in Qt Quick/QML - Part II
 
Qt Application Programming with C++ - Part 1

What's hot (20)

PDF
PDF
Qt and QML performance tips & tricks for Qt 4.7
PDF
Best Practices in Qt Quick/QML - Part IV
 
ODP
Qt Workshop
PDF
02 - Basics of Qt
PPTX
Qt for beginners part 1 overview and key concepts
 
PDF
QThreads: Are You Using Them Wrong?
 
PDF
Best Practices in Qt Quick/QML - Part III
 
PDF
Best Practices in Qt Quick/QML - Part 3
 
PPTX
Hello, QML
PPTX
Qt Framework Events Signals Threads
PDF
Qt Internationalization
 
PDF
Introduction to the Qt Quick Scene Graph
 
PPTX
Bare Metal Cluster with Kubernetes, Istio and Metallb | Nguyen Phuong An, Ngu...
PPTX
Qt test framework
 
PDF
Introduction to QML
PDF
Qt Design Patterns
PDF
Basics of Model/View Qt programming
 
PDF
Qt multi threads
ODP
Unit testing with Qt test
Qt and QML performance tips & tricks for Qt 4.7
Best Practices in Qt Quick/QML - Part IV
 
Qt Workshop
02 - Basics of Qt
Qt for beginners part 1 overview and key concepts
 
QThreads: Are You Using Them Wrong?
 
Best Practices in Qt Quick/QML - Part III
 
Best Practices in Qt Quick/QML - Part 3
 
Hello, QML
Qt Framework Events Signals Threads
Qt Internationalization
 
Introduction to the Qt Quick Scene Graph
 
Bare Metal Cluster with Kubernetes, Istio and Metallb | Nguyen Phuong An, Ngu...
Qt test framework
 
Introduction to QML
Qt Design Patterns
Basics of Model/View Qt programming
 
Qt multi threads
Unit testing with Qt test
Ad

Similar to Best Practices in Qt Quick/QML - Part 4 (20)

PDF
Practical Model View Programming (Roadshow Version)
PPTX
Asp.net mvc training
PPTX
ASP.Net 5 and C# 6
PDF
Angular JS2 Training Session #1
PDF
Object Oriented Programming (OOP) using C++ - Lecture 1
PPTX
C concepts and programming examples for beginners
PPT
lecture 6 javascript event and event handling.ppt
PPTX
Asp.NET MVC
ZIP
PPTX
Javascript
PDF
Best Practices in Qt Quick/QML - Part 2
 
PDF
Best Practices in Qt Quick/QML - Part 2
PPTX
AngularJS
PDF
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
PDF
Into The Box 2018 - CBT
PPTX
chapter 5 Templates-Introduction in C++.pptx
PDF
elm-d3 @ NYC D3.js Meetup (30 June, 2014)
PDF
PDF
CS 32 Final Review Fall 2024 ucla school data
PPTX
Practical Model View Programming (Roadshow Version)
Asp.net mvc training
ASP.Net 5 and C# 6
Angular JS2 Training Session #1
Object Oriented Programming (OOP) using C++ - Lecture 1
C concepts and programming examples for beginners
lecture 6 javascript event and event handling.ppt
Asp.NET MVC
Javascript
Best Practices in Qt Quick/QML - Part 2
 
Best Practices in Qt Quick/QML - Part 2
AngularJS
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Into The Box 2018 - CBT
chapter 5 Templates-Introduction in C++.pptx
elm-d3 @ NYC D3.js Meetup (30 June, 2014)
CS 32 Final Review Fall 2024 ucla school data
Ad

More from ICS (20)

PDF
Understanding the EU Cyber Resilience Act
 
PDF
Porting Qt 5 QML Modules to Qt 6 Webinar
 
PDF
Medical Device Cybersecurity Threat & Risk Scoring
 
PDF
Exploring Wayland: A Modern Display Server for the Future
 
PDF
Threat Modeling & Risk Assessment Webinar: A Step-by-Step Example
 
PDF
8 Mandatory Security Control Categories for Successful Submissions
 
PDF
Future-Proofing Embedded Device Capabilities with the Qt 6 Plugin Mechanism.pdf
 
PDF
Choosing an Embedded GUI: Comparative Analysis of UI Frameworks
 
PDF
Medical Device Cyber Testing to Meet FDA Requirements
 
PDF
Threat Modeling and Risk Assessment Webinar.pdf
 
PDF
Secure-by-Design Using Hardware and Software Protection for FDA Compliance
 
PDF
Webinar On-Demand: Using Flutter for Embedded
 
PDF
A Deep Dive into Secure Product Development Frameworks.pdf
 
PDF
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
PDF
Practical Advice for FDA’s 510(k) Requirements.pdf
 
PDF
Accelerating Development of a Safety-Critical Cobot Welding System with Qt/QM...
 
PDF
Overcoming CMake Configuration Issues Webinar
 
PDF
Enhancing Quality and Test in Medical Device Design - Part 2.pdf
 
PDF
Designing and Managing IoT Devices for Rapid Deployment - Webinar.pdf
 
PDF
Quality and Test in Medical Device Design - Part 1.pdf
 
Understanding the EU Cyber Resilience Act
 
Porting Qt 5 QML Modules to Qt 6 Webinar
 
Medical Device Cybersecurity Threat & Risk Scoring
 
Exploring Wayland: A Modern Display Server for the Future
 
Threat Modeling & Risk Assessment Webinar: A Step-by-Step Example
 
8 Mandatory Security Control Categories for Successful Submissions
 
Future-Proofing Embedded Device Capabilities with the Qt 6 Plugin Mechanism.pdf
 
Choosing an Embedded GUI: Comparative Analysis of UI Frameworks
 
Medical Device Cyber Testing to Meet FDA Requirements
 
Threat Modeling and Risk Assessment Webinar.pdf
 
Secure-by-Design Using Hardware and Software Protection for FDA Compliance
 
Webinar On-Demand: Using Flutter for Embedded
 
A Deep Dive into Secure Product Development Frameworks.pdf
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Practical Advice for FDA’s 510(k) Requirements.pdf
 
Accelerating Development of a Safety-Critical Cobot Welding System with Qt/QM...
 
Overcoming CMake Configuration Issues Webinar
 
Enhancing Quality and Test in Medical Device Design - Part 2.pdf
 
Designing and Managing IoT Devices for Rapid Deployment - Webinar.pdf
 
Quality and Test in Medical Device Design - Part 1.pdf
 

Recently uploaded (20)

PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PPTX
history of c programming in notes for students .pptx
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PPTX
Introduction to Artificial Intelligence
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
How Creative Agencies Leverage Project Management Software.pdf
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Nekopoi APK 2025 free lastest update
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
top salesforce developer skills in 2025.pdf
How to Choose the Right IT Partner for Your Business in Malaysia
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
2025 Textile ERP Trends: SAP, Odoo & Oracle
history of c programming in notes for students .pptx
Design an Analysis of Algorithms II-SECS-1021-03
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Introduction to Artificial Intelligence
Understanding Forklifts - TECH EHS Solution
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Navsoft: AI-Powered Business Solutions & Custom Software Development
Internet Downloader Manager (IDM) Crack 6.42 Build 41
How Creative Agencies Leverage Project Management Software.pdf
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
VVF-Customer-Presentation2025-Ver1.9.pptx
Nekopoi APK 2025 free lastest update
Odoo POS Development Services by CandidRoot Solutions
Odoo Companies in India – Driving Business Transformation.pdf
Design an Analysis of Algorithms I-SECS-1021-03
top salesforce developer skills in 2025.pdf

Best Practices in Qt Quick/QML - Part 4

  • 1. © Integrated Computer Solutions, Inc. All Rights Reserved Best Practices in Qt Quick/QML Part 4 Justin Noel Senior Consulting Engineer ICS, Inc.
  • 2. © Integrated Computer Solutions, Inc. All Rights Reserved Agenda • QML Data Models • View Delegates • Performance Tips
  • 3. © Integrated Computer Solutions, Inc. All Rights Reserved Data Models
  • 4. © Integrated Computer Solutions, Inc. All Rights Reserved Model – View – Delegate Pattern • Views in QML are Model-View-Delegate • Model is an interface to data • View manages item geometries • Delegate implements item UI • Drawing graphics • Editing data
  • 5. © Integrated Computer Solutions, Inc. All Rights Reserved Models in QML • All models are lists in QML • No tables • Can be implemented using roles • No trees • Can be implemented using QSortFilterProxyModel
  • 6. © Integrated Computer Solutions, Inc. All Rights Reserved Model Roles • Roles are like a “3rd Dimension” to cells • Can be use to apply extra attributes • Visible and non-visible • These roles in basic QML are used to make complex cells • Can be used to emulate a table
  • 7. © Integrated Computer Solutions, Inc. All Rights Reserved Model Roles • Consider this ContactsListModel • One item in the list can be very complex Name Role Phone Number Role Address Role Image Role Justin Noel 230 Second Ave Waltham, MA (617 ) 621 - 0060
  • 8. © Integrated Computer Solutions, Inc. All Rights Reserved Model Types in QML • QML ListModel Item • QML list<> property • JavaScript JSON • QQmlListProperty<Type> • QList<QObject*> • QAbstractItemModel*
  • 9. © Integrated Computer Solutions, Inc. All Rights Reserved QML List Model • ListModel is a list of ListElement Items • ListElement is a list of Key/Value pairs • Key names are arbitrary • Use whatever is convenient ListView { model: contactModel } ListModel { id: contactModel ListElement { name: “Justin Noel”; phoneNumber: “(617) 621-0060” } ListElement { name: “John Doe”; phoneNumber: “(555) 555-5555” } }
  • 10. © Integrated Computer Solutions, Inc. All Rights Reserved Delegates • Roles appear as attached properties in a Delegate ListView { model: contactModel delegate: Rectangle { Column { Text { text: name } Text { text: phoneNumber } } } ListModel { id: contactModel ListElement { name: “Justin Noel”; phoneNumber: “(617) 621-0060” } ListElement { name: “John Doe”; phoneNumber: “(555) 555-5555” } }
  • 11. © Integrated Computer Solutions, Inc. All Rights Reserved QML Specialty Models • XmlListModel • Create a model from XML • Using XPath and XQuery statements • FolderListModel • Lists a directory on the disk • Not a tree
  • 12. © Integrated Computer Solutions, Inc. All Rights Reserved QML List Property Model //ContactList.qml Item { property list<Contact> contactModel: undefined ListView { model: contactModel delegate: Rectangle { Column { Text { text: name } Text { text: phoneNumer } } } } //Main.qml ContactList { contactModel: [ Contact{ name: “Justin Noel”; phoneNumber: “(617) 621-0060” }, Contact{ name:” John Doe”; phoneNumber: “(555) 555-5555” } ] }
  • 13. © Integrated Computer Solutions, Inc. All Rights Reserved JSON Model Item { property var json: [ { name:”Justin Noel” phoneNumber:”(617) 621-0060” }, { name:” John Doe” phoneNumber “(555) 555-5555” } ] ListView { model: json delegate: Rectangle { Column { Text { text: name } Text { text: phoneNumer } } } }
  • 14. © Integrated Computer Solutions, Inc. All Rights Reserved QList<QObject*> Model class Alarm : public QObject { Q_OBJECT Q_PROPERTY(Severity severity...) Q_PROPERTY(QString description...) [...] }; QML_DECLARE_METATYPE(Alarm*); class CoffeeMaker : public QObject { Q_OBJECT Q_PROPERTY(QList<Alarm*> alarms READ alarms NOTIFY alarmsChanged) public: QList<Alarm*> alarms() const { return m_alarms; } };
  • 15. © Integrated Computer Solutions, Inc. All Rights Reserved QList<QObject*> Model import MrCoffee 1.0 Rectangle { CoffeeMaker { id: maker } ListView { anchors.fill: parent model: maker.alarms } }
  • 16. © Integrated Computer Solutions, Inc. All Rights Reserved QQmlListProperty class BarChart : public QObject { Q_OBJECT Q_CLASSINFO("DefaultProperty", “bars") Q_PROPERTY(QQmlListProperty<Bar> bars READ bars NOTIFY barsChanged) public: QQmlListProperty bars() const; protected: static int barCount(QQmlListProperty<Bar>* property); static Axis* barAt(QQmlListProperty<Bar>* property, int index); static void appendBar(QQmlListProperty<Bar>* property, Bar* value); static void clearBars(QQmlListProperty<Bar>* property); private: QList<Bar*> m_bars; };
  • 17. © Integrated Computer Solutions, Inc. All Rights Reserved QQmlListProperty QQmlListProperty BarChart::bars() const { return QQmlListProperty<Bar>(this, nullptr, &BarChart::appendBar, &BarChart::barCount, &BarChart::barAt, &BarChart::clearBars); } int BarChart::barCount(QQmlListProperty<Bar>* property) { BarChart* self = qobject_cast<BarChart*>(property->object); return self->m_bars.count(); } Bar* BarChart::barAt(QQmlListProperty<Bar>* property, int index) { BarChart* self = qobject_cast<BarChart*>(property->object); return self->m_bars[index]; }
  • 18. © Integrated Computer Solutions, Inc. All Rights Reserved QQmlListProperty void BarChart::appendBar(QQmlListProperty<Bar>* property, Bar* value) { BarChart* self = qobject_cast<BarChart*>(property->object); self->m_bars.append(value); emit self->barsChanged(); } void BarChart::clearBars(QQmlListProperty<Bar>* property) { BarChart* self = qobject_cast<BarChart*>(property->object); self->m_bars.clear(); emit self->barsChanged(); }
  • 19. © Integrated Computer Solutions, Inc. All Rights Reserved QQmlListProperty import BarChart 1.0 Rectangle { BarChart { Bar { color: “red” value: 50 } Bar { color: “blue” value: 10 } } }
  • 20. © Integrated Computer Solutions, Inc. All Rights Reserved QAbstractItemModel • Data model interface from Qt Interview Framework • Originally designed for QWidgets • QListView, QTableView, QTreeView • QAbstractItemModel is a tree interface w/ roles • Remember: QML Doesn’t support Tables or Trees • Makes the interface a little confusing for those not familiar with the QWidget views
  • 21. © Integrated Computer Solutions, Inc. All Rights Reserved QAbstractListModel • QAbstractListModel is a specialized QAIM • Implements some of the tree interface • Makes it easier to implement a list • Data models should wrap data rather than store data • Simple interface
  • 22. © Integrated Computer Solutions, Inc. All Rights Reserved Alarm Model Implementation class AlarmModel : public QAbstractListModel { Q_OBJECT public: enum Roles { SeverityRole = Qt::UserRole, DescriptionRole }; AlarmModel(DataModel& data); QHash<int, QByteArray> roleNames() const; int rowCount(const QModelIndex& parent = QModelIndex()) const; QVariant data(const QModelIndex& index, int role) const; private slots: void handleAlarmAppened(); void handleAlarmRemoved(int alarm); private: DataModel& m_data; };
  • 23. © Integrated Computer Solutions, Inc. All Rights Reserved Alarm Model Implementation AlarmModel::AlarmModel(DataModel& data) : m_data(data) { connect(&data, SINGAL(alarmsAppened()), this, SLOT(handleAlarmAppened())); connect(&data, SINGAL(alarmsRemoved(int)), this, SLOT(handleAlarmRemoved(int))); } QHash<int, QByteArray> AlarmModel::roleNames() const { static QHash<int, QByteArray> roles; if(roles.isEmpty) { roles.insert(SeverityRole, “severity”); roles.insert(DescriptionRole, “description”); } return roles; }
  • 24. © Integrated Computer Solutions, Inc. All Rights Reserved Alarm Model Implementation int AlarmModel::rowCount(const QModelIndex& parent) const { if(!parent.isValid()) return m_data.alarms().size(); else return 0; } QVariant AlarmModel::data(const QModelIndex& index, int role) const { if(!index.isValid() || index.column() != 0) return QVariant(); else if(role == SeverityRole) return m_data.alarms()[index.row()].severity(); else if(role == DescriptionRole) return m_data.alarms()[index.row()].description(); }
  • 25. © Integrated Computer Solutions, Inc. All Rights Reserved Alarm Model Implementation void AlarmModel::handleAlarmAppened() { beginInsertRows(QModelIndex(), rowCount(), rowCount()); endInsertRows(); } void AlarmModel::handleAlarmRemoved(int alarm) { beginRemoveRows(QModelIndex(), alarm, alarm); endRemoveRows(); }
  • 26. © Integrated Computer Solutions, Inc. All Rights Reserved Which Model Is Right For Me? • Use Case! Use Case! Use Case! • Web Services based app • Use JSON or XmlListModel • C++ based app • Use QAbstractItemModel or QList<QObject*> • Composite QML items like BarChart • Consists of N Bar items • property list<Type>
  • 27. © Integrated Computer Solutions, Inc. All Rights Reserved Delegates
  • 28. © Integrated Computer Solutions, Inc. All Rights Reserved Delegate Performance Tips • Keep it short. Keep it Simple • Avoid Loader • Avoid Shader Effects / Graphical Effects • Avoid clip: true • Increase cacheBuffer property for smoother scrolling • At the cost of memory
  • 29. © Integrated Computer Solutions, Inc. All Rights Reserved Coupled Delegate/Model/View • Avoid tight relationships between the view properties, model roles and athedelegate Item { property var json: [ { name:”Justin Noel” icon:”jn.png” }, { name:” John Doe” icon: “jd.png” } ] ListView { model: json delegate: Rectangle { color: ListView.view.isCurrentItem ? “blue” : “white” Column { Image { source: icon } Text { text: name } } MouseArea { onClicked: doSomething(index)} } }
  • 30. © Integrated Computer Solutions, Inc. All Rights Reserved New Delegate Item • Create a new item for your Delegate ContactRow.qml ------------------------------------------------------ Rectangle { id: contactRow property alias icon: icon.source property alias text: name.text property bool isSelected: false signal clicked() color: isSelected ? “blue” : “white” Column { Image { id: icon } Text { id: text } } MouseArea { onClicked: contactRow.clicked() } }
  • 31. © Integrated Computer Solutions, Inc. All Rights Reserved Delegate Abstraction Item { property var json: [ { name:”Justin Noel” icon:”jn.png” }, { name:” John Doe” icon: “jd.png” } ] ListView { model: json delegate: ContactRow { isSelected: ListView.view.isCurrentItem text: modelData.name icon: modelData.icon onClicked: doSomething(index) } }
  • 32. © Integrated Computer Solutions, Inc. All Rights Reserved Performance Tips
  • 33. © Integrated Computer Solutions, Inc. All Rights Reserved Be Asynchronous • Never spend more than a couple of milliseconds within blocking functions • 60Hz drawing leaves 16ms to get work done • Or frames get dropped! • User worker threads to do heavy lifting • QThread or QML WorkerScript • Never manually spin the event loop • QCoreApplication::processEvents() • This was sorta-kinda acceptable for with widgets
  • 34. © Integrated Computer Solutions, Inc. All Rights Reserved C++ Type Conversions • Avoid variant type QML properties • Marked as deprecated • Use var instead • Still try to use a specific type if you can • Assigning list types can be expensive • Optimizations implemented are made for • QString, QUrl, int, bool, qreal, pointer types
  • 35. © Integrated Computer Solutions, Inc. All Rights Reserved Animations • Animating properties will cause bindings to update • Usually what is wanted • If not use PropertyAction to “unbind” temporarily • Or create a second animatedValue property • See Bar Chart Example
  • 36. © Integrated Computer Solutions, Inc. All Rights Reserved Rendering Performance • Avoid Clipping • Very expensive • Hide non-visible items (visible = false) • Off screen items • Completely obscured items • QtQuick will call rendering methods for all visible items
  • 37. © Integrated Computer Solutions, Inc. All Rights Reserved Startup Performance • Load as little QML as possible at startup • main.qml loads a splash screen • main.qml uses async loader to show 1st screen • Connect loader.progress to an indicator • main.qml hides splash screen when • loader.status === Loader.Ready • From here load the screens as the user finds them • Using Loader or component.createObject()
  • 38. © Integrated Computer Solutions, Inc. All Rights Reserved Runtime Performance • Use lazy loading to load screens on demand • Cache screens as they are found • Or at least common screens • Caching screens causes two side effects • Increase in memory footprint • Processing of bindings for items not on the screen
  • 39. © Integrated Computer Solutions, Inc. All Rights Reserved Processing Bindings Off Screen • Bindings are re-calculated when property NOTIFY signals are emitted • On screen or not • This might not be a bad thing • If your system is mostly idle • Might as well update bindings while system is idle • Rather than fetch all the data and re-calc when switching screens which might be animated • Use case dependent. YMMV.
  • 40. © Integrated Computer Solutions, Inc. All Rights Reserved Memory Usage • QML uses quite a bit of memory • Typical app is around 10MB resident • Qt internals is making this better • Delete items made with Component createObject • Use destroy() • Delete uncommon dialogs after the user is done with them • Trading memory for screen reload performance
  • 41. © Integrated Computer Solutions, Inc. All Rights Reserved Processor Performance • QtQuick 2 is OpenGL ES 2.0 based • But some things still need to be run on the main processor • Animations @ 60 Hz require about 30% of the lowend TI AM3358 CPU* • Code from event handlers can only block for 16ms max • Or frames will be dropped • User will notice if it’s bad enough
  • 42. © Integrated Computer Solutions, Inc. All Rights Reserved Fake Animations • If you just need small animated indicators and are very short on processor power…. • Consider AnimatedImage • Takes an animated GIF • 15fps is around 5 percent CPU • User won’t notice
  • 43. © Integrated Computer Solutions, Inc. All Rights Reserved Thank You! Justin Noel Senior Consulting Engineer ICS, Inc.