Namespaces

Variants
Actions

Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries over the next few weeks. Thanks for all your past and future contributions.

How to create dynamic QML component by XML

From Wiki
Jump to: navigation, search

This article explains how to create dynamic QML component by XML.

By now we develop software according to a DDU mode, i.e: Develop-Deploy-Upgrade. When Software has been deployed, if there are upgrades, we often go to internet and download upgrade packages and then upgrade the software. The UIs are often limited to some pages. With the progress of IT technique, people would think if there is a way to avoid upgrading or we just only upgrade in servers, when people look through the information, the client UI will change by the server design, That is the idea I share with you and I will demonstrate in Qt/QML Meego development.

Introduction

One day I take part in a team to develop the CMB-meego project. I am responsible for the film ticket buying module. When I accept the task. I think at once out to realize it using XmlListModel plus PathView technique to finish it. but when I would complete it, the customer came and said it's not their wish, the Page is limited, when they want to change the style,the page won't change at all, I write the page like below:

import QtQuick 1.0
import QtWebKit 1.0
 
Rectangle
{
id: film
width: 100
height: 62
Component {
id: delegate
Column {
Image {
anchors.horizontalCenter:
name.horizontalCenter;
width: 120; height: 120;
source: src
}
Text { text: title; font.pointSize: 16 }
}
}
PathView {
anchors.fill: parent
model:zhaohang_xmlModel
delegate: delegate
path: Path {
startX: 120; startY: 100
PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
PathQuad { x: 120; y: 100; controlX: -20; controlY: 75 }
}
}
XmlListModel {
id: zhaohang_xmlModel
source: http//q.mobi:8080/movie/m/gm.p?
query: "/page/vbox/cover/item"
XmlRole { name: "title"; query: "@title/string()" }
XmlRole { name: "src"; query: "@pic/string()" }
XmlRole { name: "subtitle"; query: "@subtitle/string()" }
XmlRole { name: "request"; query: "@url/string()" }
}
}

We also discuss using webbrowser component. The webbrowser component can't supply increasing user experiences. So if there is a way we define the style and model in server, produce xml document, then we parse the document in client and reproduce the user interface. this is the subject I write today. I name it "How to create dynamic QML component by XML".

Solution

Article Metadata
Tested withCompatibility
Platform(s):
Symbian
Platform Security
Signing Required: Self Signed
Capabilities: NetworkServices
Article
Keywords: QT QML XML Component
Created: zebinluo (16 Jul 2011)
Last edited: hamishwillee (11 Oct 2012)

We define the XML document as below:

<page>
<header>
<hbox class="cmb2_header1">
<image class="image" src="cmb_icon_3.png" align="center" />
<image class="cmb2_image1" src="cmb2_favorite.png" hover="cmb2_favorites.png">
<request page="http//q.mobi:8080/zhaohang-widget-new2/normal.do" params="method=shoucang1" />
</image>
</hbox>
</header>
<vbox>
<vbox class="vbox2">
<gridbox>
<image src="girdbox_icon_19.png" hover="girdbox_icon_19a.png">
<request page="http//q.mobi:8080/zhaohang-widget-new2/normal.do" params="method=yp" />
</image>
<image src="girdbox_icon_1.png" hover="girdbox_icon_1a.png">
<request page="http//q.mobi:8080/zhaohang-widget-new2/normal.do" params="method=tehui1" />
</image>
...
</gridbox>
</vbox>
</page>

In this XML document, we define about ten kinds of element, they are page、header、 hbox、vbox---they represent the container in Qt development,and class represent the css style as html,it define like "cmb2_header1{background:url(:/cmbImages/tube/header_bg3.png)" ,image as a Image in QML, src as source and request as a singal when you click on the image. params as parameter passby etc. How can we parse this XML document and reunion as a QML page, I study the QML structure and find it is combined with components such as Rectangle、BorderImage、Image、Text etc and layouted by Row、Flow、Column etc. and we have an Item component, it can load a page like below:

Item { 
height: 60
width: 160
Loader {
anchors.fill: parent
source:"c:/test.qml"
}
}

Especially,every component is started with "{" and end with "}", these are I think about and I find a kind of solution. We parse the XML document, when we encounter a container tag such as page、hbox、vbox、gridbox,we product a new page. we use Item to load in its parent page. in pages we have the layout, for example hbox has Row, vbox has Column and gridbox has Flow etc Now let's see how to produced.

PageQML is class to produce a new page, it has construct function and destructor function, it will produce a page?.qml in the directory passed by strDir parameter, pageNumber is a static int type, I use it to produce defferent page's id and the page's number replace the "?" above.

#include "pageqml.h"
PageQML::PageQML(QString strDir,QString type)
{
this->strDir = strDir;
this->type = type;
//Produce a new page
file.setFileName(strDir+"/page"+ ++pageNumber+".qml");
QDir(strDir).mkdir(strDir);
if (!file.open(QIODevice::WriteOnly)) {
qDebug(strDir.toAscii().data());
qDebug("Cannot open file for writing: page.qml ");
}
else
{
QTextStream out(&file);
out<<"import QtQuick 1.0"<<endl;
out<<"Rectangle {"<<endl;
out<<"id:page"<<pageNumber<<endl;
out<<"width: 160"<<endl;
out<<"height: 40"<<endl;
out<<"BorderImage {"<<endl;
out<<"anchors.fill: parent"<<endl;
}
 
}
PageQML::~PageQML()
{
this->strDir = strDir;
QTextStream out(&file);
out<<"}\n"<<endl;//BorderImage
out<<"}\n"<<endl;//Page
file.close();
}
int PageQML::pageNumber=0;
 
In ParseXml class we parse XML string like this
 
bool ParseXml::XmlAnalyzer(QString strData,QString strDir)
{
PageQML super_p(strDir,"first");
super_p.setVboxLayout();
 
...
QString temp("initial");
if ( node.nodeName() == "header" )
{
super_p.addItem();
//add an Item in first page
PageQML p(strDir+"/header","header");//make a new director header and produce a new page
ParseContainerNode(headerChildNode,p);
..
}
void ParseXml::ParseContainerNode(QDomNode containerNode,PageQML &p)
{
 
if(containerNode.nodeName() == "vbox")
{
p.addItem();
PageQML pbox(p.strDir+"/vbox","vbox");
....
p.closeItem(p.strDir+"/vbox/page"+PageQML::pageNumber+".qml")
}
////////////////////////////////////
 
void PageQML::closeItem(QString source)
{
QTextStream out(&file);
QString temp("source: \""+source+"\"");
out<<temp<<endl;
out<<"}"<<endl;
out<<"}"<<endl;
}

Result

Does this works?, Let's see the directory produced.

D:/QT/MerchantsBank_Qml-build-simulator/debug/page1.qml
 
D:/QT/MerchantsBank_Qml-build-simulator/debug/page2.qml
 
D:/QT/MerchantsBank_Qml-build-simulator/debug/header/page3.qml
 
D:/QT/MerchantsBank_Qml-build-simulator/debug/header/hbox/page4.qml
 
D:/QT/MerchantsBank_Qml-build-simulator/debug/vbox/page5.qml
 
D:/QT/MerchantsBank_Qml-build-simulator/debug/vbox/vbox/page6.qml
 
D:/QT/MerchantsBank_Qml-build-simulator/debug/vbox/vbox/vbox/page7.qml
 
D:/QT/MerchantsBank_Qml-build-simulator/debug/vbox/vbox/gridbox/page8.qml

Page1.qml

import QtQuick 1.0
 
Rectangle {
id:page1
width: 160
height: 40
BorderImage {
 
anchors.fill: parent
 
Column
 
{
 
anchors.fill: parent
 
Item {
 
height: 60
 
anchors.right: parent.right
 
anchors.rightMargin: 0
 
anchors.left: parent.left
 
anchors.leftMargin: 0
 
Loader {
 
anchors.fill: parent
 
source: "D:/QT/MerchantsBank_Qml-build-simulator/debug/header/page2.qml"
 
}
 
}
 
Item {
 
height: 60
 
anchors.right: parent.right
 
anchors.rightMargin: 0
 
anchors.left: parent.left
 
anchors.leftMargin: 0
 
Loader {
 
anchors.fill: parent
 
source: "D:/QT/MerchantsBank_Qml-build-simulator/debug/vbox/page4.qml"
 
}
 
}
 
}
 
}
 
}


Page7.qml

import QtQuick 1.0
Rectangle {
id:page7
width: 160
height: 40
BorderImage {
anchors.fill: parent
Flow
{
anchors.fill: parent
BorderImage {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_left_bg_shu.png"
Image {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_icon_19.png"
}
}
BorderImage {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_left_bg_shu.png"
Image {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_icon_1.png"
}
}
BorderImage {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_left_bg_shu.png"
Image {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_icon_4.png"
}
}
BorderImage {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_left_bg_shu.png"
Image {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_icon_9.png"
}
}
BorderImage {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_left_bg_shu.png"
Image {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_icon_3.png"
}
}
BorderImage {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_left_bg_shu.png"
Image {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_icon_8.png"
}
}
BorderImage {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_left_bg_shu.png"
Image {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_icon_10.png"
}
}
BorderImage {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_left_bg_shu.png"
Image {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_icon_18.png"
}
}
BorderImage {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/girdbox_left_bg_shu.png"
Image {
source:"D:/QT/MerchantsBank_Qml-build-simulator/debug/cmbImages/tube/cmb2_shoujicaip.png"
}
}
}
}
}

Component.PNG

This page was last modified on 11 October 2012, at 01:20.
393 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×