How to make a QML Component a Singleton?
来源:互联网 发布:网络宣传方法 编辑:程序博客网 时间:2024/05/17 03:37
In this tutorial I’ll walk you through how to define a custom QML Component as a singleton.
UPDATE: I uploaded a new sample code which better outlines the difference between using an instance of MyStyleObject and using the singleton MySingletonStyleObject.You can download it here.
Currently I’m working on a rather large Qt Quick application which will be deployed on an embedded device. I’m starting to notice performance issues as we add more and more screens to the application. I decided to run the QML Profiler that is part of Qt Creator and one of the things I noticed was that one of our QML Components is being created 1500+ times. This component is an Item which holds a number of properties defining different styling options like what the colour Blue is for our purposes; its our style sheet. The issue being that its loading non-standard fonts which is expensive so as it turns out we’re loading the fonts 1500+ times.
Each screen/page in the application is instantiating its own copy of the style object as we weren’t really keen on defining one globally and simply referring to it. I mean really there is nothing wrong with that approach per-say but it does relay on a dependency; that someone instantiated the object somewhere in the application and that the objects id never changes.
So how can I reduce the number of instantiated objects without depending on a locked in stone id name?
Enter the Singleton
So as it turns out Qt Quick does have a mechanism to let you define a QML component as a singleton. I didn’t even think to see if that was even an option, a college mentioned it to me in passing and they only knew about it as a one line statement on a blog post.
Ok so its a thing but how do you do it?
There are three steps you need to do; first you need to use the pragma Singleton keyword in your QML script, then you need to register the component as a singleton, and lastly you need to import it into your other QML scripts which are going to use it.
Step 1: Declaring the QML Component as a Singleton
Lets say this is your style sheet QML object that you want to make a singleton.
- //MyStyleObject.qml
- import QtQuick 2.0
- Item {
- readonly property string colourBlue: "blue"
- readonly property string colourRed: "red"
- readonly property int fontPointSize: 16
- }
To declare it as a singleton you need to add the keywords pragma Singleton to the top of the script file.
- //MyStyleObject.qml
- pragma Singleton
- import QtQuick 2.0
- Item {
- readonly property string colourBlue: "blue"
- readonly property string colourRed: "red"
- readonly property int fontPointSize: 16
- }
Step 2: Registering the Component
Now you have two options you can either register the Component in C++ or by using a qmldir file.
To register the singleton via C++ somewhere in your C++ code you need to call qmlRegisterSingletonType().
- #include <QtQml>
- ...
- qmlRegisterSingletonType( QUrl("file:///absolute/path/MyStyleObject.qml"), "ca.imaginativethinking.tutorial.style", 1, 0, "MyStyle" );
- ...
If adding the call to qmlRegisterSingletonType() won’t work for you, maybe this is a Qt Quick UI project (i.e. no C++ ) then you can add a file called qmldir to the directory where your MyStyleObject.qml file exists. When importing a directory the QML Engine first looks for the qmldir file and uses it to import the scripts found in that directory; if the file does not exist it will import the scripts found with default values (i.e. non-singletons and uses the file name as the component name). The qmldir file can define different names to be used instead of the file name and can also tell the import to register the script as a singleton.
Here is what the directory structure should look like:
/root + absolute | + path | | + qmldir | | + MyStyleObject.qml | | + AnotherObject.qml | | + MyButton.qml | | + MySwitch.qml | + main.qml
Here is how to define the qmldir file:
- singleton MyStyle 1.0 MyStyleObject.qml
- MyOtherObject 1.0 AnotherObject.qml
- MyButton 1.0 MyButton.qml
Step 3: Importing and Using the Singleton
If you use the C++ option above then in order to import and use the singleton in your QML script you need to import the module you defined via the second parameter of qmlRegisterSingletonType() then access the object using the registered name (parameter three of qmlRegisterSingletonType()).
- //main.qml
- import QtQuick 2.0
- import ca.imaginativethinking.tutorial.style 1.0
- Rectangle {
- anchors.fill: parent
- color: MyStyle.colourBlue // <-- Notice that to access the singleton I use the object name not id (i.e. Capital M)
- }
If you used the qmldir approach then you simply need to import the directory which will register all the scripts under that directory.
- //main.qml
- import QtQuick 2.0
- import "path"
- Rectangle {
- anchors.fill: parent
- color: MyStyle.colourBlue // <-- Notice that to access the singleton I use the object name not id (i.e. Capital M)
- }
Note here however that if main.qml was within the path directory you would still have to import the path as it does not appear that the qmldir file gets used when you relay on the auto look up path.
So what does this buy us?
Example time: lets say we create an app that shows 100 blue boxes with red boarders on the screen. We'll use the MyStyleObject component to hold what shade of blue Blue is and the thickness of the boarder.
How we'll achieve this is by using a GridView with a integer model of 100 and the MyStyleObject will be created within the delegate.
- GridView {
- anchors.fill: parent
- model: 100
- delegate: gridDelegate
- cellHeight: 50
- cellWidth: cellHeight
- }
- Component {
- id: gridDelegate
- Rectangle {
- width: 50
- height: width
- color: myStyle.colourBlue
- border.color: myStyle.colourRed
- border.width: myStyle.borderSize
- Text {
- anchors.centerIn: parent
- text: index
- font.pointSize: myStyle.fontPointSize
- color: myStyle.colourWhite
- }
- MyStyleObject {
- id: myStyle
- }
- }
- }
We can run the QML Profiler in Qt Creator (Analyze -> QML Profiler) it will switch Qt Creator over to the Analyze view and launch our application.
Once our application has launched we can press the stop button on the Analyze view to terminate the application and stop the profiler. It will then load the data into the view.
By instantiating an instance of the MyStyleObject within the delegate you can see it gets created 100 times which takes 12.084ms; binded to 99 times which takes 1.130ms and that the compile phase for the object (which only happens once) takes 708.820µs.
If we change this into a singleton and run the same profiler we'll find that now the object is only created once (474.917µs); although the compile phase does take longer (1.917ms) your still saving about 10ms. This might not seem like a lot over all but when your trying to keep the presentation of your application at 60FPS every little bit helps.
- GridView {
- anchors.fill: parent
- model: 100
- delegate: gridDelegate
- cellHeight: 50
- cellWidth: cellHeight
- }
- Component {
- id: gridDelegate
- Rectangle {
- width: 50
- height: width
- color: MyStyle.colourBlue // <-- Capital M MyStyle means I'm now access the one and only instance of the MySingletonStyle object
- border.color: MyStyle.colourRed
- border.width: MyStyle.borderSize
- Text {
- anchors.centerIn: parent
- text: index
- font.pointSize: MyStyle.fontPointSize
- color: MyStyle.colourWhite
- }
- }
- }
So there you go that is all you have to do to define a QML Component as a singleton so that it only gets created once.
You can download a sample application which illustrate the above here:
QML Singleton Sample 1.1 - Updated to be more clear.
转载:http://imaginativethinking.ca/make-qml-component-singleton/
- How to make a QML Component a Singleton?
- How To Make A Keygen
- How to make a patch
- how-to-make-a-rpg
- How to make a ipcamera
- How to Use a QSqlQueryModel in QML
- How to creating a Component of Joomla
- How to Write a Custom Swing Component
- How to create a new component
- How to write a thread-safe Singleton?
- How To Make a Tag Cloud
- how to make a JAR file
- how to make a driver pagable
- HOW TO - Make a Roomba Serial Interface
- How to Make Exercise a Daily Habit
- How To Make A Cookie Stealer
- How to Make a Bochs Disk Image
- How to make a good presentation
- mysql5.5 慢日志slow log
- JAVA_OA(六):SpringMVC登陆实例
- 第16周实践项目1(2)——小玩文件
- 跨平台开发框架 weex 上手
- PL/SQL Developer连接本地Oracle 11g 64位数据库
- How to make a QML Component a Singleton?
- 数学特殊符号及读法
- 使用MyBatis(七)使用java注解完成CRUD
- Unity Shader Example 7 (溶解)
- iOS开发:Object-C的反射机制
- SpringMVC学习笔记:表单的数据回显
- 设计模式笔记:状态模式&策略模式
- 实现复数类中的运算符重载 完整类
- 形状类族的中的纯虚函数