source: trunk/doc/src/getting-started/gettingstartedqml.qdoc@ 1039

Last change on this file since 1039 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 43.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the documentation of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:FDL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in a
14** written agreement between you and Nokia.
15**
16** GNU Free Documentation License
17** Alternatively, this file may be used under the terms of the GNU Free
18** Documentation License version 1.3 as published by the Free Software
19** Foundation and appearing in the file included in the packaging of this
20** file.
21**
22** If you have questions regarding the use of this file, please contact
23** Nokia at [email protected].
24** $QT_END_LICENSE$
25**
26****************************************************************************/
27
28/*!
29 \page gettingstartedqml.html
30 \title Getting Started Programming with QML
31 \ingroup gettingStarted
32
33 Welcome to the world of QML, the declarative UI language. In this Getting
34 Started guide, we will create a simple text editor application using QML.
35 After reading this guide, you should be ready to develop your own applications
36 using QML and Qt C++.
37
38 \section1 Installation
39
40 First, we would need to install the latest version of Qt that includes \l{Qt
41 Quick}, which is Qt 4.7. The \l{Installation} {installation} guide contains
42 installation instructions and requirements for different platforms.
43
44 Qt Quick includes a declarative language called
45 \l{Introduction to the QML language}{QML}, the \l{Qt Declarative Module}, and
46 \l{QML Viewer}.
47
48 \section1 QML to Build User Interfaces
49
50 The application we are building is a simple text editor that will load, save,
51 and perform some text manipulation. This guide will consist of two parts. The
52 first part will involve designing the application layout and behaviors using
53 declarative language in QML. For the second part, file loading and saving will
54 be implemented using Qt C++. Using
55 \l {The Meta-Object System}{Qt's Meta-Object System}, we can expose C++ functions
56 as properties that QML elements can use. Utilizing QML and Qt C++, we can
57 efficiently decouple the interface logic from the application logic.
58
59 \image qml-texteditor5_editmenu.png
60
61 The final source code is in the \c{examples/tutorials/gettingStarted/gsQml}
62 directory. You may need to compile the C++ plugin in the
63 \c{examples/tutorials/gettingStarted/gsQml/} first. This will put the
64 C++ plugin in a directory where the QML files may find it.
65
66 To launch the text editor, merely provide the included \l{QML Viewer}{qmlviewer}
67 tool with the QML file as the argument. The C++ portion of this tutorial assumes
68 that the reader possesses basic knowledge of Qt's compilation procedures.
69
70 Tutorial chapters:
71 \list 1
72 \o \l {Defining a Button and a Menu}{Defining a Button and a Menu}
73 \o \l {Implementing a Menu Bar}{Implementing a Menu Bar}
74 \o \l {Building a Text Editor}{Building a Text Editor}
75 \o \l {Decorating the Text Editor}{Decorating the Text Editor}
76 \o \l {Extending QML using Qt C++}{Extending QML using Qt C++}
77 \endlist
78
79 \section1 Defining a Button and a Menu
80
81 \section2 Basic Component - a Button
82
83 We start our text editor by building a button. Functionally, a button has a mouse
84 sensitive area and a label. Buttons perform actions when a user presses the button.
85
86 In QML, the basic visual item is the \l {Rectangle}{Rectangle} element. The
87 \c Rectangle element has properties to control the element's appearance and location.
88
89 \snippet examples/tutorials/gettingStarted/gsQml/parts/part0/Button.qml document
90
91 First, the \c { import QtQuick 1.0 } allows the qmlviewer tool to import the QML elements
92 we will later use. This line must exist for every QML file. Notice that the version
93 of Qt modules is included in the import statement.
94
95 This simple rectangle has a unique identifier, \c simplebutton, which is bound to the
96 id property. The \c Rectangle element's properties are bound to values by listing the
97 property, followed by a colon, then the value. In the code sample, the color \c grey
98 is bound to the the Rectangle's \c color property. Similarly, we bind the \c width
99 and \c height of the Rectangle.
100
101 The \l {Text}{Text} element is a non-editable text field. We name this \c Text element
102 \c buttonLabel. To set the string content of the Text field, we bind a value to the
103 \c text property. The label is contained within the Rectangle and in order to center
104 it in the middle, we assign the \c anchors of the Text element to its parent, which
105 is called \c simplebutton. Anchors may bind to other items' anchors, allowing layout
106 assignments simpler.
107
108 We shall save this code as \c SimpleButton.qml. Running qmlviewer with the file as the
109 argument will display the grey rectangle with a text label.
110
111 \image qml-texteditor1_simplebutton.png
112
113 To implement the button click functionality, we can use QML's event handling. QML's event
114 handling is very similar to \l {Signals & Slots}{Qt's signal and slot} mechanism. Signals
115 are emitted and the connected slot is called.
116
117 \code
118 Rectangle{
119 id:simplebutton
120 ...
121
122 MouseArea{
123 id: buttonMouseArea
124
125 anchors.fill: parent //anchor all sides of the mouse area to the rectangle's anchors
126 //onClicked handles valid mouse button clicks
127 onClicked: console.log(buttonLabel.text + " clicked" )
128 }
129 }
130 \endcode
131
132 We include a \l{MouseArea} element in our simplebutton. \c MouseArea elements describe
133 the interactive area where mouse movements are detected. For our button, we anchor the
134 whole MouseArea to its parent, which is \c simplebutton. The \c anchors.fill syntax is
135 one way of accessing a specific property called \c fill inside a group of properties
136 called \c anchors. QML uses \l {Anchor-based Layout in QML}{anchor based layouts} where
137 items can anchor to another item, creating robust layouts.
138
139 The \c MouseArea has many signal handlers that are called during mouse movements within
140 the specified \c MouseArea boundaries. One of them is \c onClicked and it is called
141 whenever the acceptable mouse button is clicked, the left click being the default. We
142 can bind actions to the onClicked handler. In our example, \c console.log() outputs text
143 whenever the mouse area is clicked. The function \c console.log() is a useful tool for
144 debugging purposes and for outputting text.
145
146 The code in \c SimpleButton.qml is sufficient to display a button on the screen and
147 output text whenever it is clicked with a mouse.
148
149 \code
150 Rectangle {
151 id: button
152 ...
153
154 property color buttonColor: "lightblue"
155 property color onHoverColor: "gold"
156 property color borderColor: "white"
157
158 signal buttonClick()
159 onButtonClick: {
160 console.log(buttonLabel.text + " clicked" )
161 }
162
163 MouseArea{
164 onClicked: buttonClick()
165 hoverEnabled: true
166 onEntered: parent.border.color = onHoverColor
167 onExited: parent.border.color = borderColor
168 }
169
170 //determines the color of the button by using the conditional operator
171 color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor
172 }
173 \endcode
174
175 A fully functioning button is in \c Button.qml. The code snippets in this article
176 have some code omitted, denoted by ellipses because they were either introduced
177 earlier in the previous sections or irrelevant to the current code discussion.
178
179 Custom properties are declared using the \c {property type name} syntax. In the
180 code, the property \c buttonColor, of type \c color, is declared and bound to
181 the value \c{"lightblue"}. The \c buttonColor is later used in a conditional
182 operation to determine the buttons's fill color. Note that property value
183 assignment is possible using the \c= equals sign, in addition to value binding
184 using the \c : colon character. Custom properties allow internal items to be
185 accessible outside of the Rectangle's scope. There are basic
186 \l{QML Basic Types}{QML types} such as \c int, \c string, \c real, as well as
187 a type called \c variant.
188
189 By binding the \c onEntered and \c onExited signal handlers to colors, the
190 button's border will turn yellow when the mouse hovers above the button and
191 reverts the color when the mouse exits the mouse area.
192
193 A \c buttonClick() signal is declared in \c Button.qml by placing the \c signal
194 keyword in front of the signal name. All signals have their handlers automatically
195 created, their names starting with \c on. As a result, the \c onButtonClick is
196 \c buttonClick's handler. The \c onButtonClick is then assigned an action to
197 perform. In our button example, the \c onClicked mouse handler will simply call
198 \c onButtonClick, which displays a text. The \c onButtonClick enables outside
199 objects to access the \c {Button}'s mouse area easily. For example, items may
200 have more than one \c MouseArea declarations and a \c buttonClick signal can
201 make the distinction between the several \c MouseArea signal handlers better.
202
203 We now have the basic knowledge to implement items in QML that can handle
204 basic mouse movements. We created a \c Text label inside a \c Rectangle,
205 customized its properties, and implemented behaviors that respond to mouse
206 movements. This idea of creating elements within elements is repeated
207 throughout the text editor application.
208
209 This button is not useful unless used as a component to perform an action.
210 In the next section, we will soon create a menu containing several of these
211 buttons.
212
213 \image qml-texteditor1_button.png
214
215 \section2 Creating a Menu Page
216
217 Up to this stage, we covered how to create elements and assign behaviors inside
218 a single QML file. In this section, we will cover how to import QML elements and how
219 to reuse some of the created components to build other components.
220
221 Menus display the contents of a list, each item having the ability to perform an action.
222 In QML, we can create a menu in several ways. First, we will create a menu containing
223 buttons which will eventually perform different actions. The menu code is in
224 \c FileMenu.qml.
225
226 \code
227 import QtQuick 1.0 \\import the main Qt QML module
228 import "folderName" \\import the contents of the folder
229 import "script.js" as Script \\import a Javascript file and name it as Script
230 \endcode
231
232 The syntax shown above shows how to use the \c import keyword. This is required to
233 use JavaScript files, or QML files that are not within the same directory. Since
234 \c Button.qml is in the same directory as \c FileMenu.qml, we do not need to import
235 the \c Button.qml file to use it. We can directly create a \c Button element by declaring
236 \c Button{}, similar to a \c Rectangle{} declaration.
237
238 \code
239 In FileMenu.qml:
240
241 Row{
242 anchors.centerIn: parent
243 spacing: parent.width/6
244
245 Button{
246 id: loadButton
247 buttonColor: "lightgrey"
248 label: "Load"
249 }
250 Button{
251 buttonColor: "grey"
252 id: saveButton
253 label: "Save"
254 }
255 Button{
256 id: exitButton
257 label: "Exit"
258 buttonColor: "darkgrey"
259
260 onButtonClick: Qt.quit()
261 }
262 }
263 \endcode
264
265 In \c FileMenu.qml, we declare three \c Button elements. They are declared
266 inside a \l {Row}{Row} element, a positioner that will position its children
267 along a vertical row. The \c Button declaration resides in Button.qml,
268 which is the same as the \c Button.qml we used in the previous section.
269 New property bindings can be declared within the newly created buttons,
270 effectively overwriting the properties set in \c Button.qml. The button
271 called \c exitButton will quit and close the window when it is clicked.
272 Note that the signal handler \c onButtonClick in \c Button.qml will be
273 called in addition to the \c onButtonClick handler in \c exitButton.
274
275 \image qml-texteditor1_filemenu.png
276
277 The \c Row declaration is declared in a \c Rectangle, creating a rectangle
278 container for the row of buttons. This additional rectangle creates an indirect
279 way of organizing the row of buttons inside a menu.
280
281 The declaration of the edit menu is very similar at this stage. The menu has
282 buttons that have the labels: \c Copy, \c Paste, and \c {Select All}.
283
284 \image qml-texteditor1_editmenu.png
285
286 Armed with our knowledge of importing and customizing previously made
287 components, we may now combine these menu pages to create a menu bar,
288 consisting of buttons to select the menu, and look at how we may structure
289 data using QML.
290
291 \section1 Implementing a Menu Bar
292
293 Our text editor application will need a way to display menus using a menu bar.
294 The menu bar will switch the different menus and the user can choose which menu
295 to display. Menu switching implies that the menus need more structure than
296 merely displaying them in a row. QML uses models and views to structure data
297 and display the structured data.
298
299 \section2 Using Data Models and Views
300
301 QML has different \l{QML Data Models}{data views} that display
302 \l{QML Data Models}{data models}. Our menu bar will display the menus in a list,
303 with a header that displays a row of menu names. The list of menus are declared
304 inside a \c VisualItemModel. The \l{VisualItemModel}{\c VisualItemModel}
305 element contains items that already have views such as \c Rectangle elements
306 and imported UI elements. Other model types such as the \l{ListModel}{\c ListModel}
307 element need a delegate to display their data.
308
309 We declare two visual items in the \c menuListModel, the \c FileMenu and the
310 \c EditMenu. We customize the two menus and display them using a
311 \l {ListView}{ListView}. The \c MenuBar.qml file contains the QML declarations
312 and a simple edit menu is defined in \c EditMenu.qml.
313
314 \code
315 VisualItemModel{
316 id: menuListModel
317 FileMenu{
318 width: menuListView.width
319 height: menuBar.height
320 color: fileColor
321 }
322 EditMenu{
323 color: editColor
324 width: menuListView.width
325 height: menuBar.height
326 }
327 }
328 \endcode
329
330 The \l {ListView}{ListView} element will display a model according to a delegate.
331 The delegate may declare the model items to display in a \c Row element or display
332 the items in a grid. Our \c menuListModel already has visible items, therefore,
333 we do not need to declare a delegate.
334
335 \code
336 ListView{
337 id: menuListView
338
339 //Anchors are set to react to window anchors
340 anchors.fill:parent
341 anchors.bottom: parent.bottom
342 width:parent.width
343 height: parent.height
344
345 //the model contains the data
346 model: menuListModel
347
348 //control the movement of the menu switching
349 snapMode: ListView.SnapOneItem
350 orientation: ListView.Horizontal
351 boundsBehavior: Flickable.StopAtBounds
352 flickDeceleration: 5000
353 highlightFollowsCurrentItem: true
354 highlightMoveDuration:240
355 highlightRangeMode: ListView.StrictlyEnforceRange
356 }
357 \endcode
358
359 Additionally, \c ListView inherits from \l{Flickable}{\c Flickable}, making
360 the list respond to mouse drags and other gestures. The last portion of the
361 code above sets \c Flickable properties to create the desired flicking movement
362 to our view. In particular,the property \c highlightMoveDuration changes the
363 duration of the flick transition. A higher \c highlightMoveDuration value
364 results in slower menu switching.
365
366 The \c ListView maintains the model items through an \c index and each visual
367 item in the model is accessible through the \c index, in the order of the
368 declaration. Changing the \c currentIndex effectively changes the highlighted
369 item in the \c ListView. The header of our menu bar exemplify this effect.
370 There are two buttons in a row, both changing the current menu when clicked.
371 The \c fileButton changes the current menu to the file menu when clicked,
372 the \c index being \c 0 because \c FileMenu is declared first in the
373 \c menuListModel. Similarly, the \c editButton will change the current
374 menu to the \c EditMenu when clicked.
375
376 The \c labelList rectangle has \c z value of \c 1, denoting that it is displayed
377 at the front of the menu bar. Items with higher \c z values are displayed in front
378 of items with lower \c z values. The default \c z value is \c 0.
379
380 \code
381 Rectangle{
382 id: labelList
383 ...
384 z: 1
385 Row{
386 anchors.centerIn: parent
387 spacing:40
388 Button{
389 label: "File"
390 id: fileButton
391 ...
392 onButtonClick: menuListView.currentIndex = 0
393 }
394 Button{
395 id: editButton
396 label: "Edit"
397 ...
398 onButtonClick: menuListView.currentIndex = 1
399 }
400 }
401 }
402 \endcode
403
404 The menu bar we just created can be flicked to access the menus or by clicking
405 on the menu names at the top. Switching menu screens feel intuitive and responsive.
406
407 \image qml-texteditor2_menubar.png
408
409 \section1 Building a Text Editor
410
411 \section2 Declaring a TextArea
412
413 Our text editor is not a text editor if it didn't contain an editable text area.
414 QML's \l {TextEdit}{TextEdit} element allows the declaration of a multi-line
415 editable text area. \l {TextEdit}{TextEdit} is different from a \l {Text}{Text}
416 element, which doesn't allow the user to directly edit the text.
417
418 \code
419 TextEdit{
420 id: textEditor
421 anchors.fill:parent
422 width:parent.width; height:parent.height
423 color:"midnightblue"
424 focus: true
425
426 wrapMode: TextEdit.Wrap
427
428 onCursorRectangleChanged: flickArea.ensureVisible(cursorRectangle)
429 }
430 \endcode
431
432 The editor has its font color property set and set to wrap the text. The
433 \c TextEdit area is inside a flickable area that will scroll the text if the
434 text cursor is outside the visible area. The function \c ensureVisible() will
435 check if the cursor rectangle is outside the visible boundaries and move the
436 text area accordingly. QML uses Javascript syntax for its scripts, and as previously
437 mentioned, Javascript files can be imported and used within a QML file.
438
439 \code
440 function ensureVisible(r){
441 if (contentX >= r.x)
442 contentX = r.x;
443 else if (contentX+width <= r.x+r.width)
444 contentX = r.x+r.width-width;
445 if (contentY >= r.y)
446 contentY = r.y;
447 else if (contentY+height <= r.y+r.height)
448 contentY = r.y+r.height-height;
449 }
450 \endcode
451
452 \section2 Combining Components for the Text Editor
453
454 We are now ready to create the layout of our text editor using QML. The text
455 editor has two components, the menu bar we created and the text area. QML allows
456 us to reuse components, therefore making our code simpler, by importing components
457 and customizing when necessary. Our text editor splits the window into two;
458 one-third of the screen is dedicated to the menu bar and two-thirds of the screen
459 displays the text area. The menu bar is displayed in front of any other elements.
460
461 \code
462 Rectangle{
463
464 id: screen
465 width: 1000; height: 1000
466
467 //the screen is partitioned into the MenuBar and TextArea. 1/3 of the screen is assigned to the MenuBar
468 property int partition: height/3
469
470 MenuBar{
471 id:menuBar
472 height: partition
473 width:parent.width
474 z: 1
475 }
476
477 TextArea{
478 id:textArea
479 anchors.bottom:parent.bottom
480 y: partition
481 color: "white"
482 height: partition*2
483 width:parent.width
484 }
485 }
486 \endcode
487
488 By importing reusable components, our \c TextEditor code looks much simpler.
489 We can then customize the main application, without worrying about properties
490 that already have defined behaviors. Using this approach, application layouts
491 and UI components can be created easily.
492
493 \image qml-texteditor3_texteditor.png
494
495 \section1 Decorating the Text Editor
496 \section2 Implementing a Drawer Interface
497
498 Our text editor looks simple and we need to decorate it. Using QML, we can declare
499 transitions and animate our text editor. Our menu bar is occupying one-third of the
500 screen and it would be nice to have it only appear when we want it.