Graafisen käyttöliittymän ohjelmointi Syksy 2013 Luento 13 QML Antti Nieminen
Sisältö Johdanto QML:n perusteita JavaScript QML:ssä C++ ja QML
QML QML (Qt Meta Language tai Qt Modeling Language) on deklaratiivinen kieli käyttöliittymien tekoon Käytetään erityisesti mobiilikäyttöliittymissä Qt Quick = QML:n standardikirjasto Nämä kalvot käsittelevät QML:n ja Qt Quick:in versiota 2.0 sekä Qt:n versiota 5.0 ellei toisin mainita
QML:n etuja Yksinkertainen, deklaratiivinen syntaksi Renderöidään OpenGL:llä > nopea ja kaunis käyttöliittymä JavaScript-tuki Helposti liitettävissä C++-koodiin Voidaan toteuttaa esim. käyttöliittymä QML:llä ja sovelluslogiikka C++:lla
Esimerkki 1 import QtQuick 2.0 Rectangle { width: 360 height: 360 Text { anchors.centerin: parent text: "Hello World MouseArea { anchors.fill: parent onclicked: { Qt.quit();
QML-tiedoston suoritus QML-tiedoston voi suorittaa mm. 1. Qt:n mukana tulevalla qmlscene-sovelluksella qmlscene tiedostoni.qml 2. Luomalla Qt Creatorilla Qt Quick projektin 3. Tavallisessa Qt C++ -projektissa Tästä lisää kalvojen loppupuolella
QML on deklaratiivinen QML on deklaratiivinen kieli Deklaratiivisellä kielellä kuvataan millainen lopputulos halutaan vs. imperatiivinen kieli: määritellään vaiheet jotka suorittamalla lopputulokseen päästään QML-dokumentti voi sisältää myös imperatiivisia osia Toteutetaan JavaScript-kielellä
Deklaratiivinen vs. imperatiivinen Rectangle { id: laatikko color: blue MouseArea { onclicked: { laatikko.color = red ;
QML-dokumentti QML-dokumentti koostuu olioista, jotka muodostavat puumaisen rakenteen Yhdessä dokumentissa tasan yksi korkeimman tason olio Olion vanhempaan voi viitata parent-attribuutin kautta Rectangle { color: red Rectangle { color: parent.color
QML-olio QML-oliolle täytyy määritellä sen tyyppi Lisäksi olio voi sisältää erilaisia attribuutteja sekä lapsiolioita <OLIOTYYPPI> { <ATTRIBUUTTI1>: <ARVO1> <ATTRIBUUTTI2>: <ARVO2> <LAPSIOLIO1> <LAPSIOLIO2>
QML-oliotyypit Visuaaliset oliot (visual objects) Rectangle, Image, Text, Kaikki periytyvät Item-tyypistä Syötteenlukuoliot (user input objects) MouseArea, Keys, PinchArea, Asemointioliot (positioning objects) Positioner, Row, Column, Ja paljon muita http://qt-project.org/doc/qt-5.0/qtquick/qtquickqmltypereference.html Myös omia tyyppejään voi luoda Joko QML:llä tai C++:lla
QML-tiedostot Samassa hakemistossa oleviin QML-dokumentteihin voidaan viitata suoraan tiedoston nimellä (ilman päätettä) > näin voidaan luoda omia oliotyyppejä Laatikko.qml: Rectangle { width: 100; height: 100 Toinen.qml: Row { Laatikko { color: blue Laatikko { color: red
import QML-dokumenttiin voi importoida QMLmoduuleja, QML-hakemistoja ja JavaScripttiedostoja Oletuksena käytettävissä on kaikki saman hakemiston QML-tiedostot import QtQuick 2.0 Tarvitaan käytännössä aina Vanhemmat versiot: 1.0, 1.1 Uudemmat: 2.1, 2.2, http://qt-project.org/doc/qt-5.0/qtqml/qtqmlsyntax-imports.html
Attribuutit QML-oliot sisältävät erilaisia attribuutteja id Property-attribuutit (x,y,width,itse määritellyt, ) Erilaiset signal ja handler attribuutit http://qt-project.org/doc/qt- 5.0/qtqml/qtqml-syntax-objectattributes.html
id-attribuutti Oliolle voi asettaa id:n, jolla siihen voi viitata muista olioista Rectangle { Rectangle { id: laatikko1 color: red Rectangle { id: laatikko2 color: laatikko2.color
Property-attribuutit QML-olioiden property-attribuutit ovat tyypitettyjä Perustyypit: int, real, string, color, QML-oliotyypit: Rectangle, Item, var-tyyppiset propertyt voivat sisältää mitä vain Oman propertyn määrittely, esimerkki: Rectangle { property string tervehdys: "Moro!"
Propertyn arvo Property-attribuutit voivat sisältää joko staattisen arvon: width: 100; color: "red"; tai dynaamiseen lausekkeen: width: parent.width / 2 color: checkbox1.checked? "red" : "blue" Dynaamisessa tapauksessa propertyn arvo päivittyy automaattisesti lauseekkeen arvon muuttuessa ->
Property binding Propertyn arvon sitomista riippumaan jostain muusta/muista property(i)stä kutsutaan nimellä property binding Esim: Rectangle { width: box1.width + box2.width + 50 Aina kun jokin lausekkeen oikealla puolella olevista propertyistä muuttuu, muuttuu automaattisesti myös propertyn arvo
Esimerkki 2 import QtQuick 2.0 Rectangle { width: 400; height: 300; Rectangle { width: parent.width / 2 height: parent.height / 2 color: parent.width > parent.height? red : blue
Olion sijainti QML-olion visuaalisen sijainnin määrittämiseen on useita tapoja x- ja y-attribuutit suhteessa parent-olioon anchors-attribuutti Asetetaan suhteessa parent- tai sisar-olioon anchors.top: sisarolio.bottom Layoutit Row, Column, Grid, Flow, http://qt-project.org/doc/qt-5.0/qtquick/qtquickusecase-layouts.html
State QML-oliolle voi määritellä erilaisia tiloja (State) Olion states-attribuutti sisältää listan State-olioita State-oliossa määritellään erot olion perustilaan Perustila on nimeltään tyhjä merkkijono State { name: pohjassa ; when: mousearea.pressed PropertyChanges { target: o1; color: yellow
Esimerkki 3 Import QtQuick 2.0 Rectangle { id: root width: 400; height: 300; color: "yellow" MouseArea: { id: mousearea; anchors.fill: parent states: [ State { name: "pohjassa" when: mousearea.pressed PropertyChanges { target: root; color: "red" ]
Transitiot ja animaatiot Transitioiden avulla voidaan määritellä miten siirrytään propertyn arvosta toiseen tai tilasta toiseen Siirtymä voidaan animoida jollakin Animation-oliolla http://qt-project.org/doc/qt-5.0/qtquick/qtquick-usecaseanimations.html transitions: [Transition{ from: ; to: pohjassa ColorAnimation { duration: 1000 ]
Signaalit QML-oliotkin lähettelevät signaaleja Valmiilla QML:n oliotyypeillä on signaaleja, esim. MouseArea:n clicked Signaaleja voi määritellä myös itse signal munsignaali(string parametri) Signaali lähetetään yksinkertaisesti kutsumalla sitä JavaScriptillä munsignaali( moi );
Signaalinkäsittelijät Signaaleja voi QML:ssä vastaanottaa signaalinkäsittelijöillä (signal handlers) kuten Qt:n slotit Signaalia nimeltä foo kuunnellaan määrittelemällä olioon käsittelijä nimellä onfoo Signaalinkäsittelijä toteutetaan JavaScriptkielellä
Esimerkki 4 import QtQuick 2.0 Rectangle { width: 400; height: 300; signal jotaintapahtui(string jotain) onjotaintapahtui: { teksti.text = tapahtui + jotain; MouseArea { anchors.fill: parent onclicked: { jotaintapahtui( klikkaus ); // lähetetään signaali Text { id:teksti, text: klikkaa
Propertyjen arvojen muutos Kun propertyn bar arvo muuttuu, lähtee tästä automaattisesti signaali barchanged Muutoksia voi siis kuunnella määrittelemällä käsittelijän onbarchanged Rectangle { property real arvo onarvochanged: { //
JavaScript QML:ssä JavaScript-kieltä voidaan käyttää monella tapaa QML-dokumenteissa Property binding lausekkeet Signaalinkäsittelijät Itse määritellyt JavaScript-funktiot Importoidut JavaScript-kirjastot QML:n JavaScript ei ole aivan yhtä salliva kuin webbiselaimissa Esim. globaalia oliota (global object) ei voi muokata http://qt-project.org/doc/qt-5.0/qtqml/qtqmljavascript-expressions.html
JavaScript QML:ssä JavaScriptissa voi QML-olioihin viitata niiden id:llä Text { id: teksti, text: moi Keys.onPressed: { teksti.text +=! ; Olio nimeltä Qt sisältää joitain QML-erikoisuuksia Esim. Qt.quit(); http://qt-project.org/doc/qt-5.0/qtqml/qmlqt.html#qmlglobalqtobject
JavaScript ja property binding Property binding lauseke on käytännössä tavallinen JavaScript-lauseke, joka suoritetaan automaattisesti aina tarvittaessa width: Math.max(box1.width, box2.width) Property binding voidaan tehdä myös JavaScriptkoodissa width = Qt.binding(function(){return box1.width;) Huom! Pelkkä sijoitus ei sido vaan ainoastaan asettaa arvon kertaalleen width = box1.width
QtQuick:n moduuleita Controls Tavallisia käyttöliittymäkomponentteja QML:ssä! Qt 5.1, QtQuick 2.1 Window Tukea top-level-ikkunan toteutukseen Particles Partikkeliefektejä QML:ssä Jne.
Controls Gallery Demo qtquickcontrols/examples/quick/controls/gallery
QML:n toteutuksesta QML:n sisäinen toteutus kehittyy/muuttuu jatkuvasti Käyttöliittymän renderöinti OpenGL Pyrkii hyödyntämään mahdollisimman paljon näytönohjaimen ominaisuuksia JavaScript-moottori QML:ssä oma JavaScript-moottori Pohjana V8 Javascript Engine Räätälöity QML:n käyttötapauksiin http://blog.qt.digia.com/blog/2013/04/15/evolution-ofthe-qml-engine-part-1/
QML ja C++ QML-dokumentteja voi käsitellä Qt C++ - sovelluksella Qt C++:lla voi luoda ja muutella QML-olioita vastaanottaa QML-olioiden signaaleja kutsua QML-olioiden JavaScript-metodeita tarjota C++-olioiden metodeita QML:n käytettäväksi määritellä omia QML-oliotyyppejä jne. http://qt-project.org/doc/qt-5.0/qtqml/qtqmlcppintegration-topic.html
QML:n käyttöönotto Qt C++ -projektissa Projektitiedostossa: QT += qml quick C++:ssa esimerkiksi: QQuickView view; view.setsource(qurl::fromlocalfile("file.qml")); view.show();
QML-oliot C++:ssa Kutakin QML-oliotyyppiä vastaa jokin QObject:ista periytyvä luokka Visuaaliset oliot periytyvät luokasta QQuickItem C++-puolelta voi QML-olioita hakea niiden objectname-attribuutin perusteella Ei siis id:n
QML-oliot C++:ssa QML: Rectangle { Rectangle { objectname: olio1 C++: QQuickView* view = new QQuickView(filename); QQuickItem* olio1 = view->rootobject()-> findchild<qquickitem*>("olio1"); olio1->setproperty("color", "red");
QML-olioiden signaalit QML-olioiden signaaleja voidaan vastaanottaa C++:ssa kuin muitakin signaaleja QQuickView* view = new QQuickView("view.qml"); QObject::connect(view->rootObject(), SIGNAL(munSignaali()), view, SLOT(close())); view.qml: Rectangle { signal munsignaali
JavaScript-funktion kutsuminen QML: Rectangle { function foo(s) { return s+! ; C++: QVariant paluuarvo; QVariant parametri = moi ; QMetaObject::invokeMethod(qmlObj, foo, Q_RETURN_ARG(Qvariant, paluuarvo), Q_ARG(QVariant, parametri));
C++-olio QML:ssä C++-olioita on mahdollista määritellä QML:ssä käytettäväksi Lisätään se QML-olion kontekstiin (QQmlContext) jollain nimellä Periydyttävä joko QObject- tai QVariant-luokasta QVariant t = new QVariant( Moro ); view->rootcontext()->setcontextproperty( tervehdys, t); QML: Text { text: tervehdys
C++-metodin kutsuminen QML:ssä Jotta luokan metodia voi kutsua QML:stä on sen esittelyssä oltava Q_INVOKABLE-makro class ExampleClass : public QObject { Q_OBJECT public: Q_INVOKABLE QString examplemethod(); Lisättynä QML-kontekstiin nimellä example : Text { text: example.examplemethod()
C++-olioiden propertyt C++-olioillekin voi määritellä propertyjä Q_PROPERTY-makro Q_PROPERTY(QColor color READ color WRITE setcolor NOTIFY colorchanged) public: Qcolor color() const; void setcolor(const Qcolor &color); public signals: void colorchanged();
QML Qt-käyttöliittymässä QML-dokumentti on mahdollista "upottaa" tavalliseen Qt C++ -käyttöliittymän sisään Tätä varten QQuickWindow (tai QQuickView) on käärittävä QWidget:iin Onnistuu funktiolla QWidget::createWindowContainer (Qt 5.1) QQuickView* view = new QQuickView(filename); QWidget *container = QWidget::createWindowContainer(view); mylayout->addwidget(container);
Oliotyyppien määrittely C++:lla C++:lla voi määritellä myös oliotyyppejä QML:n käyttöön QQmlEngine::qmlRegisterType qmlregistertype<piechart>( Charts, 1, 0, PieChart ); QML: import Charts 1.0 PieChart {
QML-oliotyyppi C++:lla Esimerkki: PieChart Periytetty QQuickPaintItem-luokasta qtdeclarative/examples/qml/tutorials/extending http://qt-project.org/doc/qt- 5.0/qtqml/qtqml-cppintegrationdefinetypes.html
Yhteenveto: QML-olio QML-oliolla on kolme rajapintaa QML JavaScript C++ (QObject) C++ JavaScript QML-olio QML