📜 ⬆️ ⬇️

We work with models in QML


In continuation of the previous post , I want to tell you a little more about the new technology from Qt Software and Nokia. Let me remind you that QML is a new user interface description language, designed to simplify the development of modern applications and fill them with movement.
In this article I would like to talk a little bit about how the MVC paradigm works in QML

So that nothing will need to be compiled, to study it will be enough to have the Creator assembly with qmlviewer, it is on ftp trolls.



Let's try to do something similar to what is shown in the screenshot:

')
In Creator, you can create your own qml projects, as well as import existing directories with qml files.


As a result, a file * .qmlproject will appear, which can be opened by Creator and work no longer with separate qml files, but with entire projects.
For basic types to work, you need to include a Qt module in qml files using the import directive.
Each qml file is a module; by default, all files that are in the current directory are automatically imported.
First let's create a button:
Button.qml
import Qt 4.6

Item {
id: container

signal clicked

property string text
property bool keyUsing: false

BorderImage {
id: buttonImage
source: "images/toolbutton.sci"
width: container.width; height: container.height
}
BorderImage {
id: pressed
opacity: 0
source: "images/toolbutton.sci"
width: container.width; height: container.height
}
MouseRegion {
id: mouseRegion
anchors.fill: buttonImage
onClicked: { container.clicked(); }
}
Text {
id: btnText
color: if (container.keyUsing){ "#DDDDDD" ;} else { "#FFFFFF" ;}
anchors.centerIn: buttonImage; font.bold: true
text: container.text; style: Text.Raised; styleColor: "black"
font.pixelSize: 12
}
states: [
State {
name: "Pressed"
when: mouseRegion.pressed == true
PropertyChanges { target: pressed; opacity: 1 }
},
State {
name: "Focused"
when: container.focus == true
PropertyChanges { target: btnText; color: "#FFFFFF" }
}
]
transitions: Transition {
ColorAnimation { target: btnText; }
}

width: (btnText.width + 20)
}


* This source code was highlighted with Source Code Highlighter .

The states array describes the various states of the button, in this case there are only two of them, pressed or released. In the states themselves, the conditions under which the object enters these states are indicated. Actions that occur during the transition between states are described in the transitions array. Also, the button will emit a clicked signal that can receive and process any object.
Now we have a button module that can be used in other modules:
contactlist.qml
...
Button {
id: tagsBtn
anchors.right: parent.right;
anchors.rightMargin: 5;
y: 1;
height: (parent.height - 3)
text: " "
}
...

* This source code was highlighted with Source Code Highlighter .

In the same way, the example implements a toolbar and a search string.
Let's now move on to the model itself:
In this example, as the model used tape last added photos on flickr'a. The site provides this information in the form of rss. In qml, there is a special model for processing xml data that works on the basis of xpath .
RssModel.qml
import Qt 4.6

XmlListModel {
property string tags : ""

source: "http://api.flickr.com/services/feeds/photos_public.gne?" +(tags ? "tags=" +tags+ "&" : "" )+ "format=rss2"
query: "/rss/channel/item"
namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"

XmlRole { name: "title" ; query: "title/string()" }
XmlRole { name: "imagePath" ; query: "media:thumbnail/@url/string()" }
XmlRole { name: "url" ; query: "media:content/@url/string()" }
XmlRole { name: "description" ; query: "description/string()" }
XmlRole { name: "tags" ; query: "media:category/string()" }
XmlRole { name: "photoWidth" ; query: "media:content/@width/string()" }
XmlRole { name: "photoHeight" ; query: "media:content/@height/string()" }
XmlRole { name: "photoType" ; query: "media:content/@type/string()" }
XmlRole { name: "photoAuthor" ; query: "author/string()" }
XmlRole { name: "photoDate" ; query: "pubDate/string()" }
}

* This source code was highlighted with Source Code Highlighter .

Now we have a model in our hands that contains almost all the information from the flicker tape. Now let's try a delegate who will be responsible for displaying an element from a model, but let's not forget to make the background of neighboring elements different in brightness.
ListDelegate.qml
import Qt 4.6

Component {
Item {
id: wrapper;
width: parent.width;
height: (avatar.y + avatar.height + 15)

Rectangle {
color: "black"
opacity: index % 2 ? 0.2 : 0.3
height: wrapper.height
width: wrapper.width
y: 1
}

Rectangle {
id: avatarBorder
width: (avatar.width + 2); height: (avatar.height + 2);
color: "transparent" ;
smooth: true

Image {
id: avatar
width: 32; height: 32
source: imagePath
anchors.centerIn: parent
}

anchors.left: wrapper.left
anchors.leftMargin: 5
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: name
color: "white"
font.bold: true
style: "Raised" ; styleColor: "black"

anchors.left: avatarBorder.right
anchors.leftMargin: 10
anchors.top: avatarBorder.top
}
Text {
text: type
color: "#CCC"
font.bold: true
style: "Raised" ; styleColor: "black"

anchors.left: avatarBorder.right
anchors.leftMargin: 10
anchors.bottom: avatarBorder.bottom
}
}
}

* This source code was highlighted with Source Code Highlighter .

As we see, access to the elements of the model is very simple.
Now let's put all this together and display it with a ListView, which displays information in a simple list and has such a nice bonus as kinetic scrolling.
Create objects of the types we need and set our model and delegate to the view:
contactlist.qml
...
RssModel {
id: rssModel
}

ListModel {
id: proxyModel
}

ListDelegate {
id: listDelegate
}

ListView {
id: contactListView;
z: 0
model: contactlistModel; delegate : listDelegate;
highlight : highlight;highlightFollowsCurrentItem: true
focus: true
width: parent.width;
cacheBuffer: 100;
anchors.top: topToolBar.bottom
anchors.bottom: searchBar.top
}
...


* This source code was highlighted with Source Code Highlighter .

In addition to the model and the delegate, we set the view element to an element called highlight, it is responsible for highlighting the current element:
Component {
id: highlight
Rectangle {
width: contactListView.currentItem.width
height: contactListView.currentItem.height
color: "white" ; radius: 5; opacity: 0.3
y: SpringFollow {
source: contactListView.currentItem.y
spring: 3
damping: 0.2
}
}
}


* This source code was highlighted with Source Code Highlighter .

The SpringFollow property allows you to set the behavior of the backlight when following the current element.
Lastly, let's try to organize a search by model: To do this, create a regular model:
ListModel {
id: MyListElementsModel
ListElement {
name: "Polly"
type: "Parrot"
imagePath: "images/avatar.png"
age: 12
size: "Small"
}
...


* This source code was highlighted with Source Code Highlighter .

The search will be carried out using javascript'a, adding all the fields that meet the conditions into an intermediate proxyModel
onConfirmed: {
proxyModel.clear();
for ( var i=0;i!=contactlistModel.count;i++) {
var item = contactlistModel.get(i);
if (item.name.search(searchBar.text) != -1) {
proxyModel.append({ "name" : item.name, "type" : item.type, "imagePath" : item.imagePath});
}
}
contactListView.model = proxyModel;
}
onCancelled: {
contactListView.model = contactlistModel;
}


* This source code was highlighted with Source Code Highlighter .

The search script will be launched when the “confirm” signal from the search string comes to the onConfirmed slot. In the case of activation of the slot onCancelled view, the original model will be returned.
Screenshot showing the job search:


Both examples you can freely download and feel from my site:
Example with xml model
Search Example
You can run them either by opening the project in Creator or through the qmlviewer program, simply by pointing it to the contactlist.qml file
That's all for today. Lastly, I want to say that with qml your hair will be smooth and silky;)

Source: https://habr.com/ru/post/81549/


All Articles