Qt Quick/QML brings designers and developers together to create and collaborate. QML is a collection of technologies that can build modern and fluid interfaces for applications – quickly. Join us for this webinar to explore the best of QML for mobile, embedded and desktop.
Part IV will cover:
- Dynamic Item Creation
- Keyboard Input Handling
4. 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. Models in QML
• All models are lists in QML
• No tables
• Can be implemented using roles
• No trees
• Can be implemented using QSortFilterProxyModel
6. 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. 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
54 B Middlesex Tpke
Bedford, MA
(617 ) 621 - 0060
9. 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. 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. 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. 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. JSON Model
Item {
property var json: [
{ name:”Justin Noel” phoneNumber:”(617) 621-0060” },
{ name:” John Doe” phoneNumber “(555) 555-5555” }
]
ListView {
model: json
}
14. 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;
}
};
16. 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
17. 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. 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>
24. Focus Order
• Tab order works like a linked list
• KeyNavigation is an attached property
• Executed only when this Item has focus
TextInput {
id: firstField
focus: true
KeyNavigation.tab: secondField
}
TextInput {
id: secondField
focus: true
KeyNavigation.backTab: firstField
}
25. KeyNavigation
• Navigation Possibilities
• Tab – Backtab
• Right - Left
• Down - Up
• Qt will automatically reverse a singly linked tab
order
• If you only specify (Tab, Right, Down)
• Qt will automatically do (Backtab, Left, Up)
26. Focus Property
• Only one item in a qml file can have focus =
true
• Many QML files can be composed together
• This results in more than one item with focus = true
• This is actual a good thing as focus will be stored
Item { //Main.qml
OptionsBox {
model: firstOptions
}
OptionsBox {
model: otherOptions
}
}
Item { //OptionsBox.qml
property alias model:
listView.model
ListView {
focus: true
delegate: ...
}
}
27. Active Focus
• Only one item in a QmlEngine will have
activeFocus = true
• When drawing focus effects use activeFocus
• When taking focus call forceActiveFocus()
• Set focus = true
• Sets focus on all FocusScope items in parent
hierarchy
28. FocusScope
• Proxies Focus to a child item
• Can be use directly as a wrapper item
• More often it is the base class for QML files
Item { //Main.qml
OptionsBox {
model: firstOptions
focus: true
}
OptionsBox {
model: otherOptions
}
}
FocusScope{ //OptionsBox.qml
property alias model:
listView.model
ListView {
focus: true
delegate: ...
}
}
29. FocusScope
• When a child of a FocusScope has focus
• The FocusScope will also report focus = true
• FocusScopes can be nested
•
If your application needs keyboard input
• Use FocusScope as the base class for all your
custom items
• ListViews, Loader, etc have FocusScope built in
30. Handling Keyboard Input
• Handling actual key stroke is easy
• Keys is an attached property
• Key specific handlers
• Handlers for all keys
• Like how QWidgets work
31. Key Specific Handlers
Rectangle {
color: “black”
focus: true
Image {
id: rocket
x: 150, y:150
source: “../images/rocket.svg”
transformOrigin: Item.Center
}
Keys.onLeftPressed: rocket.rotation = (rocket.rotation - 10) %360
Keys.onRightPressed: rocket.rotation = (rocket.rotation + 10) %360
//Note there are only a few specific key handler available for use
}
33. Key Event Propagation
• Key Events will propagate
• From child to parent up to the root item
• Propagation can be stopped with
• event.accepted = true
• Key event will stop at the accepted handler
36. 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
37. Optimized Binding Evaluator
• QML Engine has a binding optimizer
• Doesn’t need to invoke the full JS interpreter
• If bindings fit certain criteria
• Help it out by following some guidelines
•
Don’t go overboard enforcing these as rules
• Micro-optimized unreadable code could ensue
• Use the QML Profiler to examine JS performance
38. Binding Optimizer
• Make sure types are known at compile time
• Avoid using var as property type
• Qt Creator will underline this yellow
• Avoid assigning properties to derivative types
• Avoid caching intermediate vars in bindings
• However, this can be beneficial with full JS interpeter
39. Binding Optimizer
• Avoid calling JavaScript functions
• Even though code may be easier to read
• Includes anonymous functions
• value: function() {…}
• Avoid using symbols from JavaScript imports
40. Binding Optimizer
• Only access Properties in “Component”
Scope
• Properties of this item
• Ids of any objects in the containing component
• Properties of the root item of the component
ListView {
id: view
property cellHeight: 50 // Bad. Move to inside delegate
delegate:
Rectangle {
height: view.cellHeight
}
}
}
41. Maximize Binding Optimizer
• Avoid writing to other properties in a property
binding
• This should be obvious.
property int other: 0
value: { other = foo } //Also happens to bind value to foo
• QML_COMPILER_STATS env var
• Print statistics about how many bindings were
able to be optimized / not optimized.
42. C++ Type Conversions
• Avoid variant type QML properties
• Marked as deprecated
• Use var instead
• Assigning list types can be expensive
• Optimizations implemented are made for
• QString, QUrl, int, bool, qreal, pointer types
43. Cache results
• In non-optimized bindings cache results
• Save lookup times.
• Especially on objects not in “Component Scope”
44. Don’t Over Update Propeties
• Don’t a update property more than one in a
binding or signal handler
45. Delegates
• Keep it short. Keep it Simple
• Avoid Loader
• Avoid Shader Effects
• Avoid clip: true
• Increase cacheBuffer property for smoother
scrolling
• At the cost of memory
46. 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
47. Painting
• 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
48. 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()
49. 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
50. 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.
51. Memory Usage
• QML uses quite a bit of memory
• Typical app is around 80MB 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
52. 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
53. Fake Animations
• If you just need small animated indicators
• Consider AnimatedImage
• Takes an animated GIF
• QtQuick has some optimizations for AnimatedImage
• 15fps is around 5 percent CPU
• User won’t notice