KEMBAR78
Best Practices in Qt Quick/QML - Part 4 | PDF
© 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.

Best Practices in Qt Quick/QML - Part 4

  • 1.
    © Integrated ComputerSolutions, Inc. All Rights Reserved Best Practices in Qt Quick/QML Part 4 Justin Noel Senior Consulting Engineer ICS, Inc.
  • 2.
    © Integrated ComputerSolutions, Inc. All Rights Reserved Agenda • QML Data Models • View Delegates • Performance Tips
  • 3.
    © Integrated ComputerSolutions, Inc. All Rights Reserved Data Models
  • 4.
    © Integrated ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, Inc. All Rights Reserved Model Types in QML • QML ListModel Item • QML list<> property • JavaScript JSON • QQmlListProperty<Type> • QList<QObject*> • QAbstractItemModel*
  • 9.
    © Integrated ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, Inc. All Rights Reserved QList<QObject*> Model import MrCoffee 1.0 Rectangle { CoffeeMaker { id: maker } ListView { anchors.fill: parent model: maker.alarms } }
  • 16.
    © Integrated ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, Inc. All Rights Reserved QQmlListProperty import BarChart 1.0 Rectangle { BarChart { Bar { color: “red” value: 50 } Bar { color: “blue” value: 10 } } }
  • 20.
    © Integrated ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, Inc. All Rights Reserved Delegates
  • 28.
    © Integrated ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, Inc. All Rights Reserved Performance Tips
  • 33.
    © Integrated ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, 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 ComputerSolutions, Inc. All Rights Reserved Thank You! Justin Noel Senior Consulting Engineer ICS, Inc.