Getting Started Programming with QML/it: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
 
No edit summary
Line 1: Line 1:
=Introduzione Alla Programmazione Con <span class="caps">QML</span>=
h1. Introduzione Alla Programmazione Con QML


Benvenuti nel mondo di <span class="caps">QML</span>, il linguaggio dichiarativo per la realizzazione di interfacce utente (UI, user interface). <br /> In questa guida introduttiva, costruiremo un semplice editor di testo utilizzando <span class="caps">QML</span>. Dopo aver letto questa guida, dovresti essere pronto per sviluppare le tue applicazioni usando <span class="caps">QML</span> e Qt C++.
Benvenuti nel mondo di QML, il linguaggio dichiarativo per la realizzazione di interfacce utente (UI, user interface).<br />In questa guida introduttiva, costruiremo un semplice editor di testo utilizzando QML. Dopo aver letto questa guida, dovresti essere pronto per sviluppare le tue applicazioni usando QML e Qt C+''.
<br />h2. QML per la creazione di UI
<br />L'applicazione che svilupperemo sarà un semplice editor di testo e permetterà di caricare, salvare e modificare del testo. Questa introduzione è divisa in due parti. La prima parte si occupa dello sviluppo del layout e dei comportamenti dei componenti dell'applicazione tramite il linguaggio QML. La seconda, invece, tratta dell'implementazione delle funzioni di caricamento e salvataggio utilizzando Qt C. Grazie al &quot;Qt's Meta-Object System&amp;quot;:http://doc.qt.nokia.com/4.7/metaobjects.html, possiamo esporre le funzioni C''+ come proprietà usate da elementi del linguaggio QML. Usando QML e Qt C+'', possiamo separare efficacemente la logica del layout dalla logica riguardante le funzionalità dell'applicazione.
<br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/qml-texteditor5_editmenu.png|Immagine editor di testi]]
<br />Per eseguire il codice QML dell'esempio, è sufficiente passare come argomento allo strumento &quot;qmlviewer&amp;quot;:http://doc.qt.nokia.com/4.7/qmlviewer.html i files QML. La seguente introduzione è pensata per quei lettori che hanno almeno una minima conoscenza della procedura per la compilazione di applicazioni in Qt.
<br />Capitoli:<br /># Definizione di pulsanti e menu<br /># Implementare barra dei menu<br /># Costruire un editor di testo<br /># Decorare l'editor di testo<br /># Estendere QML attraverso Qt C''+


==<span class="caps">QML</span> per la creazione di UI==
=== Definizione di pulsanti e menu ===


L’applicazione che svilupperemo sarà un semplice editor di testo e permetterà di caricare, salvare e modificare del testo. Questa introduzione è divisa in due parti. La prima parte si occupa dello sviluppo del layout e dei comportamenti dei componenti dell’applicazione tramite il linguaggio <span class="caps">QML</span>. La seconda, invece, tratta dell’implementazione delle funzioni di caricamento e salvataggio utilizzando Qt C++. Grazie al [http://doc.qt.nokia.com/4.7/metaobjects.html Qt’s Meta-Object System] ''[doc.qt.nokia.com]'', possiamo esporre le funzioni C++ come proprietà usate da elementi del linguaggio <span class="caps">QML</span>. Usando <span class="caps">QML</span> e Qt C++, possiamo separare efficacemente la logica del layout dalla logica riguardante le funzionalità dell’applicazione.
==== Componenti base - Pulsante ====


[[Image:qml-texteditor5_editmenu.png|Immagine editor di testi]]
Iniziamo il nostro editor di testi costruendo un pulsante. Un pulsante è costituito da un'area sensibile al mouse e da un'etichetta. I pulsanti eseguono un azione alla pressione da parte dell'utente.<br />In QML, l'oggetto visuale di base è il &quot;Rectangle&amp;quot;:http://doc.qt.nokia.com/4.7/qml-rectangle.html. Il ''Rectangle'' ha le proprietà per controllare l'aspetto e la posizione degli elementi.


Per eseguire il codice <span class="caps">QML</span> dell’esempio, è sufficiente passare come argomento allo strumento [http://doc.qt.nokia.com/4.7/qmlviewer.html qmlviewer] ''[doc.qt.nokia.com]'' i files <span class="caps">QML</span>. La seguente introduzione è pensata per quei lettori che hanno almeno una minima conoscenza della procedura per la compilazione di applicazioni in Qt.
<code>import Qt 4.7


Capitoli:
Rectangle{<br /> id:simplebutton


# Definizione di pulsanti e menu
color: &quot;grey&amp;quot;<br /> width: 400; height: 400
# Implementare barra dei menu
# Costruire un editor di testo
# Decorare l’editor di testo
# Estendere <span class="caps">QML</span> attraverso Qt C++


===Definizione di pulsanti e menu===
Text {<br /> id: buttonLabel<br /> text: &quot;button label&amp;quot;<br /> anchors.centerIn:parent<br /> }<br />}</code>


====Componenti base – Pulsante====
Innanzitutto, la riga ''import Qt 4.7'' abilita il tool qmlviewer all'importazione di elementi QML. Questa linea deve essere presente in ogni file QML. Si noti che la versione dei moduli di Qt è inclusa nella dichiarazione.


Iniziamo il nostro editor di testi costruendo un pulsante. Un pulsante è costituito da un’area sensibile al mouse e da un’etichetta. I pulsanti eseguono un azione alla pressione da parte dell’utente.<br /> In <span class="caps">QML</span>, l’oggetto visuale di base è il [http://doc.qt.nokia.com/4.7/qml-rectangle.html Rectangle] ''[doc.qt.nokia.com]''. Il ''Rectangle'' ha le proprietà per controllare l’aspetto e la posizione degli elementi.
Il ''Rectangle'' ha un identificatore univoco, ''simplebutton'', che è associato alla proprietà ''id''. Le properità del ''Rectangle'' sono specificate definendone prima il nome e, dopo il simbolo : (due punti), il valore. Nel codice di esempio, il colore ''grey'' è legato alla proprietà ''color'' del ''Rectangle''. Stessa cosa per larghezza e altezza (''width'' e ''height'').
 
L'elemento &quot;Text&amp;quot;:http://doc.qt.nokia.com/4.7/qml-text.html è un campo di testo non editabile. Lo chiameremo ''buttonLabel''. Per impostare il contenuto del campo di testo, assoceremo un valore alla sua proprietà ''text''. L'etichetta è contenuta all'interno del rectangle, e per centrarla in mezzo, colleghiamo gerarchicamente le ''anchors'' (ancore) dell’elemento ''Text'' al suo genitore, che nel nostro caso si chiama ''simplebutton''.<br />Ogni ancora può essere collegata alle ancore di altri elementi; in questo modo si semplifica la definizione della disposizione reciproca degli elementi.
 
Salveremo il tutto come ''SimpleButton.qml''. Lanciando qmlviewer con il nome del file creato come argomento, verrà mostrato a schermo un rettangolo grigio con un'etichetta di testo.


Innanzitutto, la riga ''import Qt 4.7'' abilita il tool qmlviewer all’importazione di elementi <span class="caps">QML</span>. Questa linea deve essere presente in ogni file <span class="caps">QML</span>. Si noti che la versione dei moduli di Qt è inclusa nella dichiarazione.
p=. [[Image:http://doc.qt.nokia.com/4.7/images/qml-texteditor1_simplebutton.png|pulsante grigio con etichetta testo]]


Il ''Rectangle'' ha un identificatore univoco, ''simplebutton'', che è associato alla proprietà ''id''. Le properità del ''Rectangle'' sono specificate definendone prima il nome e, dopo il simbolo : (due punti), il valore. Nel codice di esempio, il colore ''grey'' è legato alla proprietà ''color'' del ''Rectangle''. Stessa cosa per larghezza e altezza (''width'' e ''height'').
Per implementare l'evento click sul pulsante, possiamo usare la gestione degli eventi di QML. La gestione eventi di QML è molto simile al meccanismo &quot;signal e slot&amp;quot;:http://doc.qt.nokia.com/4.7/signalsandslots.html di Qt. Un segnale sarà emesso e il relativo slot connesso sarà chiamato.
 
<code>


L’elemento [http://doc.qt.nokia.com/4.7/qml-text.html Text] ''[doc.qt.nokia.com]'' è un campo di testo non editabile. Lo chiameremo ''buttonLabel''. Per impostare il contenuto del campo di testo, assoceremo un valore alla sua proprietà ''text''. L’etichetta è contenuta all’interno del rectangle, e per centrarla in mezzo, colleghiamo gerarchicamente le ''anchors'' (ancore) dell’elemento ''Text'' al suo genitore, che nel nostro caso si chiama ''simplebutton''.<br /> Ogni ancora può essere collegata alle ancore di altri elementi; in questo modo si semplifica la definizione della disposizione reciproca degli elementi.
Rectangle{<br /> id:simplebutton<br />


Salveremo il tutto come ''SimpleButton.qml''. Lanciando qmlviewer con il nome del file creato come argomento, verrà mostrato a schermo un rettangolo grigio con un’etichetta di testo.
MouseArea{<br /> id: buttonMouseArea


[[Image:qml-texteditor1_simplebutton.png|pulsante grigio con etichetta testo]]
anchors.fill: parent //ancora tutti i lati della MouseArea ai lati del rettangolo<br /> //onClicked gestisce click del mouse validi<br /> onClicked: console.log(buttonLabel.text + &quot; clicked&amp;quot; )<br /> }<br /> }


Per implementare l’evento click sul pulsante, possiamo usare la gestione degli eventi di <span class="caps">QML</span>. La gestione eventi di <span class="caps">QML</span> è molto simile al meccanismo [http://doc.qt.nokia.com/4.7/signalsandslots.html signal e slot] ''[doc.qt.nokia.com]'' di Qt. Un segnale sarà emesso e il relativo slot connesso sarà chiamato.
</code>


Aggiungiamo un elemento [http://doc.qt.nokia.com/4.7/qml-mousearea.html MouseArea] ''[doc.qt.nokia.com]'' nel nostro componente ''simplebutton''. Gli elementi ''MouseArea'' descrivono l’area interattiva dove i movimenti del mouse sono rilevati. Per il nostro pulsante, ancoriamo l’intera ''MouseArea'' al suo genitore (''parent''), il ''simplebutton''. La sintassi ''anchors.fill'' è un modo per accedere ad una specifica proprietà chiamata ''fill'' all’interno di un gruppo di proprietà denominate ''anchors''. <span class="caps">QML</span> utilizza [http://doc.qt.nokia.com/4.7/qml-anchor-layout.html layouts basati su ancore] ''[doc.qt.nokia.com]'', dove gli elementi possono ancorarsi ad altri elementi, creando layout robusti e flessibili.
Aggiungiamo un elemento &quot;MouseArea&amp;quot;:http://doc.qt.nokia.com/4.7/qml-mousearea.html nel nostro componente ''simplebutton''. Gli elementi ''MouseArea'' descrivono l'area interattiva dove i movimenti del mouse sono rilevati. Per il nostro pulsante, ancoriamo l'intera ''MouseArea'' al suo genitore (''parent''), il ''simplebutton''. La sintassi ''anchors.fill'' è un modo per accedere ad una specifica proprietà chiamata ''fill'' all'interno di un gruppo di proprietà denominate ''anchors''. QML utilizza &quot;layouts basati su ancore&amp;quot;:http://doc.qt.nokia.com/4.7/qml-anchor-layout.html, dove gli elementi possono ancorarsi ad altri elementi, creando layout robusti e flessibili.


La ''MouseArea'' ha molti gestori di segnali che possono essere chiamati durante i movimenti del mouse all’interno dei limiti specificati. Uno di questi è ''onClicked'' ed è invocato ogni qualvolta viene cliccato un pulsante valido del mouse; il pulsante di default è quello sinistro. Possiamo legare azioni al gestore ''onClicked''. Nel nostro esempio, ''console.log()'' visualizza testo ogni volta che viene cliccata la MouseArea. La funzione ''console.log()'' è uno strumento utile per scopi di debugging e, in generale, per visualizzare del testo in output.
La ''MouseArea'' ha molti gestori di segnali che possono essere chiamati durante i movimenti del mouse all'interno dei limiti specificati. Uno di questi è ''onClicked'' ed è invocato ogni qualvolta viene cliccato un pulsante valido del mouse; il pulsante di default è quello sinistro. Possiamo legare azioni al gestore ''onClicked''. Nel nostro esempio, ''console.log()'' visualizza testo ogni volta che viene cliccata la MouseArea. La funzione ''console.log()'' è uno strumento utile per scopi di debugging e, in generale, per visualizzare del testo in output.


Il codice in ''SimpleButton.qml'' è sufficiente per mostrare un bottone sullo schermo e visualizzare del testo ogni volta che viene cliccato con il mouse.
Il codice in ''SimpleButton.qml'' è sufficiente per mostrare un bottone sullo schermo e visualizzare del testo ogni volta che viene cliccato con il mouse.


Un pulsante completamente funzionante è ''Button.qml''. Il codice visualizzato in questo articolo omette alcune parti, denotate da “…”, poiché sono già state introdotte nella sezione precedente o comunque sono irrilevanti ai fini della discussione di questo specifico codice.
<code><br />Rectangle {<br /> id:Button<br /> …


Per dichiarare proprietà personalizzate si utilizza la sintassi: ''proprietà tipo nome''. Nel codice, viene dichiarata la proprietà ''buttonColor'', di tipo ''color'', e vincolata al valore ''lightblue''. La proprietà ''buttonColor'' è utilizzata successivamente in un’operazione condizionale per determinare il colore di riempimento del bottone. Si noti che per assegnare dei valori alle proprietà è possibile utilizzare il segno uguale "="oppure il segno due punti ":". Le proprietà personalizzate permettono di rendere accessibili elementi interni all’elemento ''Rectangle'', anche dall’esterno del suo campo di visibiltà. Esistono diversi [http://doc.qt.nokia.com/4.7/qdeclarativebasictypes.html tipi <span class="caps">QML</span>] ''[doc.qt.nokia.com]'' di base come ''int'', ''string'', ''real'', ma anche un tipo generico chiamato ''variant''.
property color buttonColor: &quot;lightblue&amp;quot;<br /> property color onHoverColor: &quot;gold&amp;quot;<br /> property color borderColor: &quot;white&amp;quot;
 
signal buttonClick()<br /> onButtonClick: {<br /> console.log(buttonLabel.text + &quot; clicked&amp;quot; )<br /> }
 
MouseArea{<br /> onClicked: buttonClick()<br /> hoverEnabled: true<br /> onEntered: parent.border.color = onHoverColor<br /> onExited: parent.border.color = borderColor<br /> }
 
// determina il colore del bottone utilizando l'operatore condizionale<br /> color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor<br />}<br /></code>
 
Un pulsante completamente funzionante è ''Button.qml''. Il codice visualizzato in questo articolo omette alcune parti, denotate da &quot;…&quot;, poiché sono già state introdotte nella sezione precedente o comunque sono irrilevanti ai fini della discussione di questo specifico codice.
 
Per dichiarare proprietà personalizzate si utilizza la sintassi: ''proprietà tipo nome''. Nel codice, viene dichiarata la proprietà ''buttonColor'', di tipo ''color'', e vincolata al valore &quot;''lightblue''&quot;. La proprietà ''buttonColor'' è utilizzata successivamente in un'operazione condizionale per determinare il colore di riempimento del bottone. Si noti che per assegnare dei valori alle proprietà è possibile utilizzare il segno uguale &amp;quot;=&amp;quot;oppure il segno due punti &amp;quot;:&amp;quot;. Le proprietà personalizzate permettono di rendere accessibili elementi interni all’elemento ''Rectangle'', anche dall’esterno del suo campo di visibiltà. Esistono diversi &quot;tipi QML&amp;quot;:http://doc.qt.nokia.com/4.7/qdeclarativebasictypes.html di base come ''int'', ''string'', ''real'', ma anche un tipo generico chiamato ''variant''.


Legando i gestori dei segnali ''onEntered'' ed ''onExited'' ai colori, il colore del bordo del pulsante diventa giallo quando il mouse si sposta sopra di esso e ritorna del colore pecedente quando il mouse esce dalla ''MouseArea''.
Legando i gestori dei segnali ''onEntered'' ed ''onExited'' ai colori, il colore del bordo del pulsante diventa giallo quando il mouse si sposta sopra di esso e ritorna del colore pecedente quando il mouse esce dalla ''MouseArea''.


Un segnale ''buttonClick()'' è dichiarato in ''Button.qml'' inserendo la parola chiave ''signal'' davanti al nome del segnale. Per ogni segnale vengono create automaticamente le relative funzioni di gestione, i cui nomi iniziano con il prefisso ''on''. Come risultato si ha che il gestore di ''buttonClick'' è ''onButtonClick''. All’''onButtonClick'' è successivamente assegnata un’azione da svolgere. Nel nostro esempio, il gestore del mouse ''onClicked'' chiamerà semplicemente ''onButtonClick'', il quale ha il compito di visualizzare del testo. ''onButtonClick'' permette ad oggetti esterni di accedere facilmente alla ''MouseArea'' del ''Button''. Inoltre, gli elementi possono avere dichiarate più di una ''MouseArea'', ed avere il segnale ''buttonClick'' permette di distinguere meglio i diversi gestori di segnali delle varie ''MouseArea''.
Un segnale ''buttonClick()'' è dichiarato in ''Button.qml'' inserendo la parola chiave ''signal'' davanti al nome del segnale. Per ogni segnale vengono create automaticamente le relative funzioni di gestione, i cui nomi iniziano con il prefisso ''on''. Come risultato si ha che il gestore di ''buttonClick'' è ''onButtonClick''. All'''onButtonClick'' è successivamente assegnata un'azione da svolgere. Nel nostro esempio, il gestore del mouse ''onClicked'' chiamerà semplicemente ''onButtonClick'', il quale ha il compito di visualizzare del testo. ''onButtonClick'' permette ad oggetti esterni di accedere facilmente alla ''MouseArea'' del ''Button''. Inoltre, gli elementi possono avere dichiarate più di una ''MouseArea'', ed avere il segnale ''buttonClick'' permette di distinguere meglio i diversi gestori di segnali delle varie ''MouseArea''.


Ora abbiamo le conoscenze essenziali per implementare in <span class="caps">QML</span> oggetti che possono gestire i principali movimenti del mouse. Abbiamo creato un’etichetta ''Text'' all’interno di un ''Rectangle'', personalizzato le sue proprietà ed implementato dei comportamenti che rispondano ai movimenti del mouse. Questa idea di base della creazione di elementi all’interno di altri elementi, si ripresenterà nello sviluppo di tutta l’applicazione di esempio.
Ora abbiamo le conoscenze essenziali per implementare in QML oggetti che possono gestire i principali movimenti del mouse. Abbiamo creato un'etichetta ''Text'' all'interno di un ''Rectangle'', personalizzato le sue proprietà ed implementato dei comportamenti che rispondano ai movimenti del mouse. Questa idea di base della creazione di elementi all’interno di altri elementi, si ripresenterà nello sviluppo di tutta l'applicazione di esempio.


Il pulsante realizzato non è molto utile se non viene usato come componente per eseguire una qualche azione. Nella prossima sezione creeremo un menu contenente alcuni di questi pulsanti.
Il pulsante realizzato non è molto utile se non viene usato come componente per eseguire una qualche azione. Nella prossima sezione creeremo un menu contenente alcuni di questi pulsanti.


[[Image:qml-texteditor1_button.png|Pulsante grigio chiaro con all'interno un'etichetta]]
p=. [[Image:http://doc.qt.nokia.com/4.7/images/qml-texteditor1_button.png|Pulsante grigio chiaro con all&#39;interno un&#39;etichetta]]
 
==== Creazione della pagina del menu ====


====Creazione della pagina del menu====
Fino ad ora abbiamo visto come creare elementi ed assegnare comportamenti all'interno di file QML. In questa sezione, scopriremo come importare elementi QML e come riutilizzare alcuni componenti creati per costruire altri componenti.


Fino ad ora abbiamo visto come creare elementi ed assegnare comportamenti all’interno di file <span class="caps">QML</span>. In questa sezione, scopriremo come importare elementi <span class="caps">QML</span> e come riutilizzare alcuni componenti creati per costruire altri componenti.
Un menu mostra il contenuto di una lista i cui elementi hanno la capacità di compiere un'azione. In QML possiamo ottnere un menu in vari modi. Prima di tutto creeremo un menu contenente dei pulsanti a cui faremo eseguire azioni differenti. Il codice del menu è in ''FileMenu.qml''.


Un menu mostra il contenuto di una lista i cui elementi hanno la capacità di compiere un’azione. In <span class="caps">QML</span> possiamo ottnere un menu in vari modi. Prima di tutto creeremo un menu contenente dei pulsanti a cui faremo eseguire azioni differenti. Il codice del menu è in ''FileMenu.qml''.
<code><br />import Qt 4.7 //Importa il modulo Qt QML principale<br />import &quot;folderName&amp;quot; //Importa il contenuto della cartella<br />import &quot;script.js&amp;quot; as Script //Importa un file javascript e lo chiama Script<br /></code>


La sintassi riportata mostra come utilizzare la parola chiave ''import''. Ciò è richiesto per utilizzare file [https://developer.mozilla.org/en/JavaScript JavaScript] ''[developer.mozilla.org]'' o <span class="caps">QML</span> che non sono nella stessa cartella. Siccome ''Button.qml'' si trova nella stessa cartella di ''FileMenu.qml'', non è necessario importare esplicitamente il file ''Button.qml'' per poterlo usare, ma possiamo creare direttamente un elemento ''Button'' dichiarando ''Button{}'', come è stato fatto per ''Rectangle{}''.
La sintassi riportata mostra come utilizzare la parola chiave ''import''. Ciò è richiesto per utilizzare file &quot;JavaScript&amp;quot;:https://developer.mozilla.org/en/JavaScript o QML che non sono nella stessa cartella. Siccome ''Button.qml'' si trova nella stessa cartella di ''FileMenu.qml'', non è necessario importare esplicitamente il file ''Button.qml'' per poterlo usare, ma possiamo creare direttamente un elemento ''Button'' dichiarando ''Button{}'', come è stato fatto per ''Rectangle{}''.


In ''FileMenu.qml'' abbiamo dichiarato tre elementi ''Button''. Essi sono definiti all’interno di un elemento di tipo ''Row'', un elemento di posizionamento che ha lo scopo di collocare i suoi figli lungo una riga orizzontale. La dichiarazione di ''Button'' si trova nel file ''Button.qml'', lo stesso che abbiamo utilizzato nella sezione precedente. Le impostazioni delle proprietà possono essere dichiarate all’interno della dichiarazione del pulsante; in questo modo si sovrascrivono le proprietà impostate in ''Button.qml''. Quando cliccato, il pulsante chiamato ''exitButton'' chiuderà l’applicazione. Si noti che il gestore di segnale ''onButtonClick'' in ''Button.qml'' sarà chiamato in aggiunta al gestore ''onButtonClick'' in ''exitButton''.
<code><br />In FileMenu.qml:


[[Image:qml-texteditor1_filemenu.png|Immagine menu File]]
Row{<br /> anchors.centerIn: parent<br /> spacing: parent.width/6


La dichiarazione dell’elemento di tipo ''Row'' è fatta all’interno di un ''Rectangle'', creando un contenitore a forma di rettangolo per la riga di pulsanti. Il rettangolo aggiuntivo permette di aver un modo indiretto di organizzare la riga di pulsanti all’interno del menu.
Button{<br /> id: loadButton<br /> buttonColor: &quot;lightgrey&amp;quot;<br /> label: &quot;Load&amp;quot;<br /> }<br /> Button{<br /> buttonColor: &quot;grey&amp;quot;<br /> id: saveButton<br /> label: &quot;Save&amp;quot;<br /> }<br /> Button{<br /> id: exitButton<br /> label: &quot;Exit&amp;quot;<br /> buttonColor: &quot;darkgrey&amp;quot;
 
onButtonClick: Qt.quit()<br /> }<br /> }<br /></code>
 
In ''FileMenu.qml'' abbiamo dichiarato tre elementi ''Button''. Essi sono definiti all'interno di un elemento di tipo ''Row'', un elemento di posizionamento che ha lo scopo di collocare i suoi figli lungo una riga orizzontale. La dichiarazione di ''Button'' si trova nel file ''Button.qml'', lo stesso che abbiamo utilizzato nella sezione precedente. Le impostazioni delle proprietà possono essere dichiarate all'interno della dichiarazione del pulsante; in questo modo si sovrascrivono le proprietà impostate in ''Button.qml''. Quando cliccato, il pulsante chiamato ''exitButton'' chiuderà l'applicazione. Si noti che il gestore di segnale ''onButtonClick'' in ''Button.qml'' sarà chiamato in aggiunta al gestore ''onButtonClick'' in ''exitButton''.
 
p=. [[Image:http://doc.qt.nokia.com/4.7/images/qml-texteditor1_filemenu.png|Immagine menu File]]
 
La dichiarazione dell'elemento di tipo ''Row'' è fatta all'interno di un ''Rectangle'', creando un contenitore a forma di rettangolo per la riga di pulsanti. Il rettangolo aggiuntivo permette di aver un modo indiretto di organizzare la riga di pulsanti all'interno del menu.


La dichiarazione del menu di editing è molto simile a quella precedente. Questo menù è composto da pulsanti con le etichette ''Copy'', ''Paste'' e ''Select All''.
La dichiarazione del menu di editing è molto simile a quella precedente. Questo menù è composto da pulsanti con le etichette ''Copy'', ''Paste'' e ''Select All''.


[[Image:qml-texteditor1_editmenu.png|Immagine menu Edit]]
p=. [[Image:http://doc.qt.nokia.com/4.7/images/qml-texteditor1_editmenu.png|Immagine menu Edit]]
 
Forti della conoscenza acquisita sull'importazione e sulla personalizzazione dei componenti, possiamo ora combinare queste pagine di menu per creare una singola barra dei menu, composta da pulsanti per selezionare il menu, e vedere come strutturare i dati usando QML.
 
=== Implementare la barra dei menu ===
 
Il nostro editor di testi necessità di un modo per visualizzare i menu tramite una barra dei menu. La barra dei menu proporrà i diversi menu attraverso cui l'utente potrà navigare. Per il cambio del menu occorrerà una struttura più complessa della semplice visualizzazione su una riga. QML utilizza modelli e viste per gestire e visualizzare i dati strutturati.
 
==== Usare la struttura modello-vista ====
 
QML dispone di diverse &quot;viste&amp;quot;:http://doc.qt.nokia.com/4.7/qdeclarativemodels.html per visualizzare i &quot;modelli&amp;quot;:http://doc.qt.nokia.com/4.7/qdeclarativemodels.html. La nostra barra dei menu visualizzerà i menu in una lista, con un'intestazione che mostrerà i nomi dei menu su una riga. L'elenco dei menu è dichiarato all'interno di un ''VisualItemModel''. L'elemento &quot;VisualItemModel&amp;quot;:http://doc.qt.nokia.com/4.7/qml-visualitemmodel.html contiene gli oggetti che hanno già delle viste, come l'oggetto ''Rectangle'' e gli altri elementi dell'interfaccia. Altri tipi di modelli, come l'elemento &quot;ListModel&amp;quot;:http://doc.qt.nokia.com/4.7/qml-listmodel.html, necessitano di un delegato per visualizzare i propri dati.


Forti della conoscenza acquisita sull’importazione e sulla personalizzazione dei componenti, possiamo ora combinare queste pagine di menu per creare una singola barra dei menu, composta da pulsanti per selezionare il menu, e vedere come strutturare i dati usando <span class="caps">QML</span>.
Dichiariamo quindi due elementi visuali nel ''menuListModel'', il ''FileMenu'' e ''EditMenu'', li personalizziamo e li visualizziamo usando il &quot;ListView&amp;quot;:http://doc.qt.nokia.com/4.7/qml-listview.html. Il file ''MenuBar.qml'' contiene le dichiarazioni QML e un semplice menu di modifica è definito nel file ''EditMenu.qml''.


===Implementare la barra dei menu===
<code> VisualItemModel{<br /> id: menuListModel<br /> FileMenu{<br /> width: menuListView.width<br /> height: menuBar.height<br /> color: fileColor<br /> }<br /> EditMenu{<br /> color: editColor<br /> width: menuListView.width<br /> height: menuBar.height<br /> }<br /> }</code>


Il nostro editor di testi necessità di un modo per visualizzare i menu tramite una barra dei menu. La barra dei menu proporrà i diversi menu attraverso cui l’utente potrà navigare. Per il cambio del menu occorrerà una struttura più complessa della semplice visualizzazione su una riga. <span class="caps">QML</span> utilizza modelli e viste per gestire e visualizzare i dati strutturati.
L'elemento ''ListView'' visualizza un modello attraverso il suo elemento delegato. Il delegato può definire che gli elementi del modello da visualizzare siano disposti in una riga o in una griglia. Il nostro ''menuListModel'' ha già degli oggetti visibili, quindi non abbiamo bisogno di dichiarare un delegato.


====Usare la struttura modello-vista====
<code><br /> ListView{<br /> id: menuListView


<span class="caps">QML</span> dispone di diverse [http://doc.qt.nokia.com/4.7/qdeclarativemodels.html viste] ''[doc.qt.nokia.com]'' per visualizzare i [http://doc.qt.nokia.com/4.7/qdeclarativemodels.html modelli] ''[doc.qt.nokia.com]''. La nostra barra dei menu visualizzerà i menu in una lista, con un’intestazione che mostrerà i nomi dei menu su una riga. L’elenco dei menu è dichiarato all’interno di un ''VisualItemModel''. L’elemento [http://doc.qt.nokia.com/4.7/qml-visualitemmodel.html VisualItemModel] ''[doc.qt.nokia.com]'' contiene gli oggetti che hanno già delle viste, come l’oggetto ''Rectangle'' e gli altri elementi dell’interfaccia. Altri tipi di modelli, come l’elemento [http://doc.qt.nokia.com/4.7/qml-listmodel.html ListModel] ''[doc.qt.nokia.com]'', necessitano di un delegato per visualizzare i propri dati.
//Le anchors sono settate per adattarsi alla finestra<br /> anchors.fill:parent<br /> anchors.bottom: parent.bottom<br /> width:parent.width<br /> height: parent.height


Dichiariamo quindi due elementi visuali nel ''menuListModel'', il ''FileMenu'' e ''EditMenu'', li personalizziamo e li visualizziamo usando il [http://doc.qt.nokia.com/4.7/qml-listview.html ListView] ''[doc.qt.nokia.com]''. Il file ''MenuBar.qml'' contiene le dichiarazioni <span class="caps">QML</span> e un semplice menu di modifica è definito nel file ''EditMenu.qml''.
//Il model contiene i dati<br /> model: menuListModel


L’elemento ''ListView'' visualizza un modello attraverso il suo elemento delegato. Il delegato può definire che gli elementi del modello da visualizzare siano disposti in una riga o in una griglia. Il nostro ''menuListModel'' ha già degli oggetti visibili, quindi non abbiamo bisogno di dichiarare un delegato.
//Controlla il movimento del passaggio tra i menu<br /> snapMode: ListView.SnapOneItem<br /> orientation: ListView.Horizontal<br /> boundsBehavior: Flickable.StopAtBounds<br /> flickDeceleration: 5000<br /> highlightFollowsCurrentItem: true<br /> highlightMoveDuration:240<br /> highlightRangeMode: ListView.StrictlyEnforceRange<br /> }</code>


Inoltre, ''ListView'' eredita da [http://doc.qt.nokia.com/4.7/qml-flickable.html Flickable] ''[doc.qt.nokia.com]'', rendendo la lista reattiva al trascinamento del mouse ed a altre gestures. L’ultima parte di codice imposta la proprietà ''Flickable'' per creare dei movimenti di ribaltamento alla nostra vista. In particolare, la proprietà ''highlightMoveDuration'' cambia la durata della transizione: un valore più alto di ''highlightMoveDuration'' renderà il passaggio tra i menu più lento.
Inoltre, ''ListView'' eredita da &quot;Flickable&amp;quot;:http://doc.qt.nokia.com/4.7/qml-flickable.html, rendendo la lista reattiva al trascinamento del mouse ed a altre gestures. L'ultima parte di codice imposta la proprietà ''Flickable'' per creare dei movimenti di ribaltamento alla nostra vista. In particolare, la proprietà ''highlightMoveDuration'' cambia la durata della transizione: un valore più alto di ''highlightMoveDuration'' renderà il passaggio tra i menu più lento.


Il ''ListView'' gestisce gli elementi del modello attraverso un ''index'' (indice) e ogni elemento visuale nel modello è accessibile tramite questo indice, secondo l’ordine di dichiarazione. Cambiando il ''currentIndex'' cambieremo l’elemento evidenziato nella ''Listview''. L’intestazione della barra dei menu semplifica questo effetto. Ci sono due pulsanti sulla stessa riga, quando cliccati entrambi cambiano il menu corrente. Il pulsante ''fileButton'' quando cliccato cambia il menu corrente con ''FileMenu''; l’indice diventa 0 perchè ''FileMenu'' è il primo elemento dichiarato nel ''menuListModel''. Analogamente il pulsante ''editButton'' sostituisce il menu corrente con ''EditMenu''.
Il ''ListView'' gestisce gli elementi del modello attraverso un ''index'' (indice) e ogni elemento visuale nel modello è accessibile tramite questo indice, secondo l'ordine di dichiarazione. Cambiando il ''currentIndex'' cambieremo l'elemento evidenziato nella ''Listview''. L'intestazione della barra dei menu semplifica questo effetto. Ci sono due pulsanti sulla stessa riga, quando cliccati entrambi cambiano il menu corrente. Il pulsante ''fileButton'' quando cliccato cambia il menu corrente con ''FileMenu''; l'indice diventa 0 perchè ''FileMenu'' è il primo elemento dichiarato nel ''menuListModel''. Analogamente il pulsante ''editButton'' sostituisce il menu corrente con ''EditMenu''.


Il rettangolo dell’etichetta ''labelList'' ha un valore di z settato a 1, e sarà quindi visualizzata davanti alla barra dei menu. Gli oggetti con un valore di z maggiori saranno visualizzati in primo piano rispetto a quelli con un valore di z inferiore. Il valore di default di z è 0.
Il rettangolo dell'etichetta ''labelList'' ha un valore di z settato a 1, e sarà quindi visualizzata davanti alla barra dei menu. Gli oggetti con un valore di z maggiori saranno visualizzati in primo piano rispetto a quelli con un valore di z inferiore. Il valore di default di z è 0.
 
<code><br /> Rectangle{<br /> id: labelList<br /> …<br /> z: 1<br /> Row{<br /> anchors.centerIn: parent<br /> spacing:40<br /> Button{<br /> label: &quot;File&amp;quot;<br /> id: fileButton<br /> …<br /> onButtonClick: menuListView.currentIndex = 0<br /> }<br /> Button{<br /> id: editButton<br /> label: &quot;Edit&amp;quot;<br /> …<br /> onButtonClick: menuListView.currentIndex = 1<br /> }<br /> }<br /> }</code>


La barra dei menu appena creata potrà essere sfogliata per accedere ai menu oppure si può semplicemente cliccare sui nomi dei menu. Il cambiamento dei menu è intuitivo e reattivo.
La barra dei menu appena creata potrà essere sfogliata per accedere ai menu oppure si può semplicemente cliccare sui nomi dei menu. Il cambiamento dei menu è intuitivo e reattivo.


[[Image:qml-texteditor2_menubar.png|barra dei menu]]
p=. [[Image:http://doc.qt.nokia.com/4.7/images/qml-texteditor2_menubar.png|barra dei menu]]
 
=== Costruire un editor di testo ===
 
==== Dichiarare un'area di testo ====
 
Il nostro editor di testo non potrà mai essere un vero editor di testo finché non inseriremo un area di testo modificabile. L'elemento &quot;TextEdit&amp;quot;:http://doc.qt.nokia.com/4.7/qml-textedit.html permette la dichiarazione di un componente per la modifica di testo multilinea. ''TextEdit'' è diverso dall'elemento &quot;Text&amp;quot;:http://doc.qt.nokia.com/4.7/qml-text.html, che non consente all'utente di modificare direttamente il testo.
 
<code><br />TextEdit{<br /> id: textEditor<br /> anchors.fill:parent<br /> width:parent.width; height:parent.height<br /> color:&quot;midnightblue&amp;quot;<br /> focus: true
 
wrapMode: TextEdit.Wrap
 
onCursorRectangleChanged: flickArea.ensureVisible(cursorRectangle)<br /> }</code>
 
L'editor contiene proprietà per impostare il colore del testo e per farlo andare a capo. L'area di testo ''TextEdit'' è contenuta all'interno di un'area scorrevole che farà scorrere il testo se il cursore si trova al di fuori dell'area visibile. La funzione ''ensureVisible()'' controlla se il rettangolo del cursore è fuori dai confini visibili e, nel caso, sposta opportunamente l'area di testo. QML usa la sintassi Javascript per i suoi scripts, e, come accennato in precedenza, i file Javascript possono essere importati e utilizzati all'interno di un file QML.


===Costruire un editor di testo===
<code><br /> function ensureVisible®{<br /> if (contentX &gt;= r.x)<br /> contentX = r.x;<br /> else if (contentX+width &lt;= r.x+r.width)<br /> contentX = r.x+r.width-width;<br /> if (contentY &gt;= r.y)<br /> contentY = r.y;<br /> else if (contentY+height &lt;= r.y+r.height)<br /> contentY = r.y+r.height-height;<br /> }</code>


====Dichiarare un’area di testo====
==== Combinare i componenti per l'editor di testi ====


Il nostro editor di testo non potrà mai essere un vero editor di testo finché non inseriremo un area di testo modificabile. L’elemento [http://doc.qt.nokia.com/4.7/qml-textedit.html TextEdit] ''[doc.qt.nokia.com]'' permette la dichiarazione di un componente per la modifica di testo multilinea. ''TextEdit'' è diverso dall’elemento [http://doc.qt.nokia.com/4.7/qml-text.html Text] ''[doc.qt.nokia.com]'', che non consente all’utente di modificare direttamente il testo.
Ora siamo pronti per creare il layout del nostro editor di testo mediante QML. L'editor di testo ha due componenti: la barra dei menu e l'area di testo. QML ci permette di riutilizzare i componenti, rendendo il codice più semplice, attraverso l'importazione e la personalizzazione degli stessi quando necessario. Il nostro editor di testo divide la finestra in due parti, un terzo dello schermo è dedicato alla barra dei menu ed i rimanenti due terzi della schermata sono destinati alla visualizzazione dell'area di testo. La barra dei menu viene visualizzata in primo piano rispetto a qualsiasi altro elemento.


L’editor contiene proprietà per impostare il colore del testo e per farlo andare a capo. L’area di testo ''TextEdit'' è contenuta all’interno di un’area scorrevole che farà scorrere il testo se il cursore si trova al di fuori dell’area visibile. La funzione ''ensureVisible()'' controlla se il rettangolo del cursore è fuori dai confini visibili e, nel caso, sposta opportunamente l’area di testo. <span class="caps">QML</span> usa la sintassi Javascript per i suoi scripts, e, come accennato in precedenza, i file Javascript possono essere importati e utilizzati all’interno di un file <span class="caps">QML</span>.
<code> Rectangle{


====Combinare i componenti per l’editor di testi====
id: screen<br /> width: 1000; height: 1000


Ora siamo pronti per creare il layout del nostro editor di testo mediante <span class="caps">QML</span>. L’editor di testo ha due componenti: la barra dei menu e l’area di testo. <span class="caps">QML</span> ci permette di riutilizzare i componenti, rendendo il codice più semplice, attraverso l’importazione e la personalizzazione degli stessi quando necessario. Il nostro editor di testo divide la finestra in due parti, un terzo dello schermo è dedicato alla barra dei menu ed i rimanenti due terzi della schermata sono destinati alla visualizzazione dell’area di testo. La barra dei menu viene visualizzata in primo piano rispetto a qualsiasi altro elemento.
//Lo schermo è diviso in MenuBar e TextArea. La MenuBar occupa 1/3 dello schermo<br /> property int partition: height/3


Tramite l’importazione di componenti riutilizzabili, il codice del nostro editor di testo appare molto più semplice. Possiamo quindi personalizzare l’applicazione principale, senza preoccuparci delle proprietà che abbiamo già definito prima. Usando questo approccio, i layout delll’applicazione ed i componenti dell’interfaccia grafica possono essere creati ed assemblati più facilmente.
MenuBar{<br /> id:menuBar<br /> height: partition<br /> width:parent.width<br /> z: 1<br /> }


[[Image:qml-texteditor3_texteditor.png|editor di testi]]
TextArea{<br /> id:textArea<br /> anchors.bottom:parent.bottom<br /> y: partition<br /> color: &quot;white&amp;quot;<br /> height: partition*2<br /> width:parent.width<br /> }<br /> }</code>


===Decorare l’editor di testo===
Tramite l'importazione di componenti riutilizzabili, il codice del nostro editor di testo appare molto più semplice. Possiamo quindi personalizzare l'applicazione principale, senza preoccuparci delle proprietà che abbiamo già definito prima. Usando questo approccio, i layout delll'applicazione ed i componenti dell'interfaccia grafica possono essere creati ed assemblati più facilmente.


====Implementare un interfaccia a scomparsa====
p=. [[Image:http://doc.qt.nokia.com/4.7/images/qml-texteditor3_texteditor.png|editor di testi]]


Il nostro editor di testo appare semplice, ma possiamo abbellirlo. Utilizzando <span class="caps">QML</span> possiamo dichiarare delle transizioni per animarlo. La nostra barra del menu occupa un terzo dello schermo, sarebbe carino se apparisse solo quando lo vogliamo.
=== Decorare l'editor di testo ===


A tale scopo possiamo aggiungere un elemento di interfaccia (''drawer'') che si occuperà di contrarre o espandere la barra dei menu quando viene cliccata. Nella nostra implementazione abbiamo un sottile rettangolo che risponde ai click del mouse. Il ''drawer'', così come l’applicazione, ha due stati: aperto (''<span class="caps">DRAWER</span>_OPEN'') e chiuso (''<span class="caps">DRAWER</span>_CLOSED''). L’elemento ''drawer'' è una sottile striscia rettangolare al cui interno è presente un elemento [http://doc.qt.nokia.com/4.7/qml-image.html immagine] ''[doc.qt.nokia.com]'' che definisce un’icona a forma di freccia centrata all’interno dell’area. Il ''drawer'' assegna uno stato, con identificativo ''screen'', all’intera applicazione ogni volta che l’utente clicca la ''MouseArea''.
==== Implementare un interfaccia a scomparsa ====


Uno stato è semplicemente un’insieme di configurazioni predefinite e si dichiara tramite un elemento [http://doc.qt.nokia.com/4.7/qml-state.html State] ''[doc.qt.nokia.com]''. Una lista di stati può essere collegata alla proprietà ''states''. Nella nostra applicazione i due stati sono chiamati ''<span class="caps">DRAWER</span>_CLOSED'' e ''<span class="caps">DRAWER</span>_OPEN''. La configurazione dei componenti è definita negli elementi [http://doc.qt.nokia.com/4.7/qml-propertychanges.html PropertyChanges] ''[doc.qt.nokia.com]''. Nello stato ''<span class="caps">DRAWER</span>_OPEN'' quattro elementi riceveranno modifiche alle loro proprietà. Il primo, la ''menuBar'', cambia la proprietà y in 0. Similmente, la ''textArea'' si abbasserà in una nuova posizione quando lo stato è ''<span class="caps">DRAWER</span>_OPEN''. La ''textArea'', il ''drawer'' e la sua icona subiranno cambiamenti delle loro proprietà per adeguarsi allo stato corrente.
Il nostro editor di testo appare semplice, ma possiamo abbellirlo. Utilizzando QML possiamo dichiarare delle transizioni per animarlo. La nostra barra del menu occupa un terzo dello schermo, sarebbe carino se apparisse solo quando lo vogliamo.


Le variazioni tra uno stato e l’altro sono brusche, perciò necessitano di transizioni più dolci. Le transizioni tra gli stati sono definite utilizzando l’elemento [http://doc.qt.nokia.com/4.7/qml-transition.html Transition] ''[doc.qt.nokia.com]'', che può essere legato alla proprietà ''transitions'' di un elemento. il nostra editor di testo effettua transizioni quando lo stato diventa ''<span class="caps">DRAWER</span>_OPEN'' oppure ''<span class="caps">DRAWER</span>_CLOSED''. È importante sottolineare che le transizioni necessitano di uno stato di partenza (''from'') e di uno di arrivo (''to''), tuttavia, nel nostro caso, possiamo utilizzare il simbolo jolly * per indicare che la transizione si applica a tutti i cambiamenti di stato.
A tale scopo possiamo aggiungere un elemento di interfaccia (''drawer'') che si occuperà di contrarre o espandere la barra dei menu quando viene cliccata. Nella nostra implementazione abbiamo un sottile rettangolo che risponde ai click del mouse. Il ''drawer'', così come l'applicazione, ha due stati: aperto (''DRAWER_OPEN'') e chiuso (''DRAWER_CLOSED''). L'elemento ''drawer'' è una sottile striscia rettangolare al cui interno è presente un elemento &quot;immagine&amp;quot;:http://doc.qt.nokia.com/4.7/qml-image.html che definisce un'icona a forma di freccia centrata all'interno dell'area. Il ''drawer'' assegna uno stato, con identificativo ''screen'', all'intera applicazione ogni volta che l'utente clicca la ''MouseArea''.


Durante le transizioni possiamo assegnare delle animazioni ai cambiamenti di proprietà. La nostra ''menuBar'' cambia posizione da ''y:0'' a ''y:-partition'': è possibile animare questa transizione utilizzando l’elemento [http://doc.qt.nokia.com/4.7/qml-numberanimation.html NumberAnimation] ''[doc.qt.nokia.com]''. Definiamo che le proprietà dell’oggetto si animino per un certo periodo con un andamento definito da una certa curva. Una curva di andamento controlla la progressione dell’animazione, interpolando i comportamenti durante la variazione di stato. L’evoluzione della curva scelta è [http://doc.qt.nokia.com/4.7/qml-propertyanimation.html#easing.type-prop Easing.Out.Quint] ''[doc.qt.nokia.com]'' che rallenta i movimenti verso la fine dell’animazione. E’ possibile approfondire l’argomento leggendo l’articolo [http://doc.qt.nokia.com/4.7/qdeclarativeanimation.html QML’s Animation] ''[doc.qt.nokia.com]''.
<code>Rectangle{<br /> id:drawer<br /> height:15


Un altro modo per animare variazioni dei valori delle proprietà è dichiarando un elemento [http://doc.qt.nokia.com/4.7/qml-behavior.html Behaviour] ''[doc.qt.nokia.com]''. Una transizione avviene solo durante cambi di stato e ''Behaviour'' può impostare un’animazione per una modifica generica della proprietà. Nell’editor di testo, l’icona freccia ha un ''NumberAnimation'' che anima la sua proprietà ''rotation'' ad ogni cambiamento.
Image{<br /> id: arrowIcon<br /> source: &quot;images/arrow.png&amp;quot;<br /> anchors.horizontalCenter: parent.horizontalCenter<br /> }


Grazie alla conoscenza di stati ed animazioni, siamo ora in grado di migliorare l’aspetto dei nostri componenti. In ''Button.qml'' possiamo aggiungere modifiche alle proprietà ''scale'' e ''color'' quando il bottone viene premuto. I tipi colore si animano utilizzando ''ColorAnimation'', mentre i tipi numerici con ''NumberAnimation''. La sintassi ''on nomeProprietà'' mostrata sotto semplifica il lavoro quando si lavora su di una singola proprietà.
MouseArea{<br /> id: drawerMouseArea<br /> anchors.fill:parent<br /> onClicked:{<br /> if (screen.state  &amp;quot;DRAWER_CLOSED&amp;quot;)&amp;#123;
                    screen.state = &amp;quot;DRAWER_OPEN&amp;quot;
                &amp;#125;
                else if (screen.state  &quot;DRAWER_OPEN&amp;quot;){<br /> screen.state = &quot;DRAWER_CLOSED&amp;quot;<br /> }<br /> }<br /> …<br /> }<br /> }<br /></code>


Inoltre, possiamo migliorare l’aspetto dei componenti <span class="caps">QML</span> aggiungendo effetti di colore, come sfumature ed effetti di trasparenza. Dichiarando un elemento [http://doc.qt.nokia.com/4.7/qml-gradient.html Gradient] ''[doc.qt.nokia.com]'' si sovrascrive la proprietà ''color'' dell’elemento. E’ possibile definire un colore all’interno della sfumatura utilizzando l’elemento [http://doc.qt.nokia.com/4.7/qml-gradientstop.html GradientStop] ''[doc.qt.nokia.com]''. La sfumatura è valorrizata utilizzando una scala tra ''0,0'' e ''1,0''.
Uno stato è semplicemente un'insieme di configurazioni predefinite e si dichiara tramite un elemento &quot;State&amp;quot;:http://doc.qt.nokia.com/4.7/qml-state.html. Una lista di stati può essere collegata alla proprietà ''states''. Nella nostra applicazione i due stati sono chiamati ''DRAWER_CLOSED'' e ''DRAWER_OPEN''. La configurazione dei componenti è definita negli elementi &quot;PropertyChanges&amp;quot;:http://doc.qt.nokia.com/4.7/qml-propertychanges.html. Nello stato ''DRAWER_OPEN'' quattro elementi riceveranno modifiche alle loro proprietà. Il primo, la ''menuBar'', cambia la proprietà y in 0. Similmente, la ''textArea'' si abbasserà in una nuova posizione quando lo stato è ''DRAWER_OPEN''. La ''textArea'', il ''drawer'' e la sua icona subiranno cambiamenti delle loro proprietà per adeguarsi allo stato corrente.


Il gradiente è usato dalla barra del menu per simulare l’effetto di profondità. Il primo colore inizia a 0.0 e l’ultimo termina a 1.0.
<code>states:[<br /> State {<br /> name: &quot;DRAWER_OPEN&amp;quot;<br /> PropertyChanges { target: menuBar; y: 0}<br /> PropertyChanges { target: textArea; y: partition + drawer.height}<br /> PropertyChanges { target: drawer; y: partition}<br /> PropertyChanges { target: arrowIcon; rotation: 180}<br /> },<br /> State {<br /> name: &quot;DRAWER_CLOSED&amp;quot;<br /> PropertyChanges { target: menuBar; y:<s>height; }<br /> PropertyChanges { target: textArea; y: drawer.height; height: screen.height</s> drawer.height }<br /> PropertyChanges { target: drawer; y: 0 }<br /> PropertyChanges { target: arrowIcon; rotation: 0 }<br /> }<br /> ]<br /></code>


====Prossimi passi====
Le variazioni tra uno stato e l'altro sono brusche, perciò necessitano di transizioni più dolci. Le transizioni tra gli stati sono definite utilizzando l'elemento &quot;Transition&amp;quot;:http://doc.qt.nokia.com/4.7/qml-transition.html, che può essere legato alla proprietà ''transitions'' di un elemento. il nostra editor di testo effettua transizioni quando lo stato diventa ''DRAWER_OPEN'' oppure ''DRAWER_CLOSED''. È importante sottolineare che le transizioni necessitano di uno stato di partenza (''from'') e di uno di arrivo (''to''), tuttavia, nel nostro caso, possiamo utilizzare il simbolo jolly * per indicare che la transizione si applica a tutti i cambiamenti di stato.


Abbiamo terminato di costruire l’interfaccia utente di un semplice editor di testo. Proseguendo, completata l’interfaccia utente, possiamo implementare la logica dell’applicazione utilizzando Qt e C++ standard. <span class="caps">QML</span> funziona bene come strumento di prototipazione, separando efficacemente la logica dell’applicazione dal progetto dell’interfaccia utente.
Durante le transizioni possiamo assegnare delle animazioni ai cambiamenti di proprietà. La nostra ''menuBar'' cambia posizione da ''y:0'' a ''y:-partition'': è possibile animare questa transizione utilizzando l'elemento &quot;NumberAnimation&amp;quot;:http://doc.qt.nokia.com/4.7/qml-numberanimation.html. Definiamo che le proprietà dell'oggetto si animino per un certo periodo con un andamento definito da una certa curva. Una curva di andamento controlla la progressione dell'animazione, interpolando i comportamenti durante la variazione di stato. L'evoluzione della curva scelta è &quot;Easing.Out.Quint&amp;quot;:http://doc.qt.nokia.com/4.7/qml-propertyanimation.html#easing.type-prop che rallenta i movimenti verso la fine dell'animazione. E' possibile approfondire l'argomento leggendo l'articolo &quot;QML’s Animation&amp;quot;:http://doc.qt.nokia.com/4.7/qdeclarativeanimation.html.


[[Image:qml-texteditor4_texteditor.png|Interfaccia editor quasi conclusa]]
<code>transitions: [<br /> Transition {<br /> to: &quot;*&quot;<br /> NumberAnimation { target: textArea; properties: &quot;y, height&amp;quot;; duration: 100; easing.type:Easing.OutExpo }<br /> NumberAnimation { target: menuBar; properties: &quot;y&amp;quot;; duration: 100; easing.type: Easing.OutExpo }<br /> NumberAnimation { target: drawer; properties: &quot;y&amp;quot;; duration: 100; easing.type: Easing.OutExpo }<br /> }<br /> ]<br /></code>


===Estendere <span class="caps">QML</span> attraverso Qt C++===
Un altro modo per animare variazioni dei valori delle proprietà è dichiarando un elemento &quot;Behaviour&amp;quot;:http://doc.qt.nokia.com/4.7/qml-behavior.html. Una transizione avviene solo durante cambi di stato e ''Behaviour'' può impostare un'animazione per una modifica generica della proprietà. Nell'editor di testo, l'icona freccia ha un ''NumberAnimation'' che anima la sua proprietà ''rotation'' ad ogni cambiamento.


Ora che abbiamo completato il layout del nostro editor di testi, possiamo implementare le funzionalità in C++. Usando il <span class="caps">QML</span> con C++ abbiamo la possibilità di creare la logica della nostra applicazione attraverso Qt. Possiamo creare dei contenuti <span class="caps">QML</span> in un applicazione C++ usando le [http://doc.qt.nokia.com/4.7/qtbinding.html classi dichiarative Qt] ''[doc.qt.nokia.com]'' e visualizzando gli elementi <span class="caps">QML</span> usando la Graphic Scene. Altrimenti, possiamo esportare il nostro codice C++ in un plugin che potrà essere letto dal tool [http://doc.qt.nokia.com/4.7/qmlviewer.html qmlviewer] ''[doc.qt.nokia.com]''. Per la nostra applicazione implementiamo le funzioni di caricamento e salvataggio per poi esportarle come un plugin. In questo modo, dobbiamo solo caricare direttamente il file <span class="caps">QML</span> invece di eseguire un file eseguibile.
<code>In TextEditor.qml:


===Esporre classi C++ in <span class="caps">QML</span>===
Behavior{<br /> NumberAnimation{property: &quot;rotation&amp;quot;;easing.type: Easing.OutExpo }<br /> }<br /></code>


Implementeremo il caricamento e salvataggio dei file attraverso Qt e C++. Le classi e le funzioni C++ possono essere usare in <span class="caps">QML</span> registrandole. Le classi hanno bisogno di essere compilate come plugin Qt e i file <span class="caps">QML</span> devo conoscere dove sono localizzati i plugin.
Grazie alla conoscenza di stati ed animazioni, siamo ora in grado di migliorare l'aspetto dei nostri componenti. In ''Button.qml'' possiamo aggiungere modifiche alle proprietà ''scale'' e ''color'' quando il bottone viene premuto. I tipi colore si animano utilizzando ''ColorAnimation'', mentre i tipi numerici con ''NumberAnimation''. La sintassi ''on nomeProprietà'' mostrata sotto semplifica il lavoro quando si lavora su di una singola proprietà.
 
<code>In Button.qml:<br /> …
 
color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor<br /> Behavior on color { ColorAnimation{ duration: 55} }
 
scale: buttonMouseArea.pressed ? 1.1 : 1.00<br /> Behavior on scale { NumberAnimation{ duration: 55} }<br /></code>
 
Inoltre, possiamo migliorare l'aspetto dei componenti QML aggiungendo effetti di colore, come sfumature ed effetti di trasparenza. Dichiarando un elemento &quot;Gradient&amp;quot;:http://doc.qt.nokia.com/4.7/qml-gradient.html si sovrascrive la proprietà ''color'' dell'elemento. E' possibile definire un colore all'interno della sfumatura utilizzando l'elemento &quot;GradientStop&amp;quot;:http://doc.qt.nokia.com/4.7/qml-gradientstop.html. La sfumatura è valorrizata utilizzando una scala tra ''0,0'' e ''1,0''.
 
<code>In MenuBar.qml<br /> gradient: Gradient {<br /> GradientStop { position: 0.0; color: &quot;#8C8F8C&amp;quot; }<br /> GradientStop { position: 0.17; color: &quot;#6A6D6A&amp;quot; }<br /> GradientStop { position: 0.98;color: &quot;#3F3F3F&amp;quot; }<br /> GradientStop { position: 1.0; color: &quot;#0e1B20&amp;quot; }<br /> }<br /></code>
 
Il gradiente è usato dalla barra del menu per simulare l'effetto di profondità. Il primo colore inizia a 0.0 e l'ultimo termina a 1.0.
 
==== Prossimi passi ====
 
Abbiamo terminato di costruire l'interfaccia utente di un semplice editor di testo. Proseguendo, completata l’interfaccia utente, possiamo implementare la logica dell'applicazione utilizzando Qt e C++ standard. QML funziona bene come strumento di prototipazione, separando efficacemente la logica dell'applicazione dal progetto dell'interfaccia utente.
 
p=. [[Image:http://doc.qt.nokia.com/4.7/images/qml-texteditor4_texteditor.png|Interfaccia editor quasi conclusa]]
 
=== Estendere QML attraverso Qt C++ ===
 
Ora che abbiamo completato il layout del nostro editor di testi, possiamo implementare le funzionalità in C+''. Usando il QML con C''+ abbiamo la possibilità di creare la logica della nostra applicazione attraverso Qt. Possiamo creare dei contenuti QML in un applicazione C++ usando le &quot;classi dichiarative Qt&amp;quot;:http://doc.qt.nokia.com/4.7/qtbinding.html e visualizzando gli elementi QML usando la Graphic Scene. Altrimenti, possiamo esportare il nostro codice C++ in un plugin che potrà essere letto dal tool &quot;qmlviewer&amp;quot;:http://doc.qt.nokia.com/4.7/qmlviewer.html. Per la nostra applicazione implementiamo le funzioni di caricamento e salvataggio per poi esportarle come un plugin. In questo modo, dobbiamo solo caricare direttamente il file QML invece di eseguire un file eseguibile.
 
=== Esporre classi C++ in QML ===
 
Implementeremo il caricamento e salvataggio dei file attraverso Qt e C+''. Le classi e le funzioni C''+ possono essere usare in QML registrandole. Le classi hanno bisogno di essere compilate come plugin Qt e i file QML devo conoscere dove sono localizzati i plugin.


Per la nostra applicazione, dobbiamo creare i seguenti elementi:
Per la nostra applicazione, dobbiamo creare i seguenti elementi:


# Una classe ''Directory'' che gestirà le operazioni legate alle directory
# Una classe ''Directory'' che gestirà le operazioni legate alle directory
# Una classe ''File'' che sarà un [http://doc.qt.nokia.com/4.7/qobject.html QObject] ''[doc.qt.nokia.com]'', che simulerà la lista di files nella directory
# Una classe ''File'' che sarà un &quot;QObject&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html, che simulerà la lista di files nella directory
# Una classe plugin che registrerà la classe per il contenuto <span class="caps">QML</span>
# Una classe plugin che registrerà la classe per il contenuto QML
# Un progetto Qt che compilerà il plugin
# Un progetto Qt che compilerà il plugin
# Un file ''qmldir'' che informerà il tool qmlviewerfile sulla locazione del plugin
# Un file ''qmldir'' che informerà il tool qmlviewerfile sulla locazione del plugin


====Costruire il plugin Qt====
==== Costruire il plugin Qt ====


Per costruire il plugin, abbiamo bisogno di specificarlo nel file di progetto Qt. Innanzitutto, i sorgenti,gli headers e i moduli devono essere aggiunti al nostro file di progetto. Tutti i file C++ e di progetto devono essere nella directory ''filedialog''.
Per costruire il plugin, abbiamo bisogno di specificarlo nel file di progetto Qt. Innanzitutto, i sorgenti,gli headers e i moduli devono essere aggiunti al nostro file di progetto. Tutti i file C++ e di progetto devono essere nella directory ''filedialog''.
<code><br /> In cppPlugins.pro:
TEMPLATE = lib<br /> CONFIG ''= qt plugin<br /> QT''= declarative
DESTDIR ''= ../plugins<br /> OBJECTS_DIR = tmp<br /> MOC_DIR = tmp
<br /> TARGET = FileDialog
<br /> HEADERS''= directory.h  file.h  dialogPlugin.h
SOURCES += directory.cpp  file.cpp  dialogPlugin.cpp<br /></code>


In particolare, compiliamo Qt con i moduli dichiarativi e settiamolo come plugin, avremo bisogno di un lib template. Metteremo poi il plugin compilato nella sua directory padre.
In particolare, compiliamo Qt con i moduli dichiarativi e settiamolo come plugin, avremo bisogno di un lib template. Metteremo poi il plugin compilato nella sua directory padre.


====Registrare una classe in <span class="caps">QML</span>====
==== Registrare una classe in QML ====


La nostra classe plugin, ''DialogPlugin'' è una sottoclasse di [http://doc.qt.nokia.com/4.7/qdeclarativeextensionplugin.html QDeclarativeExtensionPlugin] ''[doc.qt.nokia.com]''. Dobbiamo implementare la funzione ereditata, [http://doc.qt.nokia.com/4.7/qdeclarativeextensionplugin.html#registerTypes registerTypes()] ''[doc.qt.nokia.com]''. Il file ''dialogPlugin.cpp'' si prenta cosi:
<code><br /> In dialogPlugin.h:


La funzione [http://doc.qt.nokia.com/4.7/qdeclarativeextensionplugin.html#registerTypes registerTypes()] ''[doc.qt.nokia.com]'' registra le nostre classi File e Directory in <span class="caps">QML</span>. Questa funzione necessità di un nome per la classe per il suo template, un numero di versione maggiore e minore e un nome per la nostre classi.
#include &lt;QtDeclarative/QDeclarativeExtensionPlugin&amp;gt;


Dovremmo esportare il plugin usando la macro [http://doc.qt.nokia.com/4.7/qtplugin.html#Q_EXPORT_PLUGIN2#q-export-plugin2 Q_EXPORT_PLUGIN2] ''[doc.qt.nokia.com]''. Notate nel nostro file dialogPlugin.h, abbiamo messo la macro [http://doc.qt.nokia.com/4.7/qobject.html#Q_OBJECT Q_OBJECT] ''[doc.qt.nokia.com]'' macro all’inizo della classe. Dobbiamo quindi lanciare qmake sul progetto per generare i necessari codici meta-oggetto di Qt.
class DialogPlugin : public QDeclarativeExtensionPlugin<br /> {<br /> Q_OBJECT


====Creare proprietà <span class="caps">QML</span> nella classi C++====
public:<br /> void registerTypes(const char *uri);


Possiamo creare degli elementi e delle proprietà <span class="caps">QML</span> usando C++ e il sistema meta-oggetto di Qt. Possiamo implementare delle proprietà usando gli slot e signal, per farli conoscere a Qt. Queste proprieta possono poi essere usate in <span class="caps">QML</span>.
};<br /></code>


Per l’editor di testi, abbiamo bisogno di abilitare il caricamento e salvataggio dei files. Tipicamente, queste funzionalità sono contenute in un file dialog. Fortunatamente, possiamo usare [http://doc.qt.nokia.com/4.7/qdir.html QDir] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/qfile.html QFile] ''[doc.qt.nokia.com]'' e [http://doc.qt.nokia.com/4.7/qtextstream.html QTextStream] ''[doc.qt.nokia.com]'' per implementare la lettura delle cartelle e i flussi di input/output.
La nostra classe plugin, ''DialogPlugin'' è una sottoclasse di &quot;QDeclarativeExtensionPlugin&amp;quot;:http://doc.qt.nokia.com/4.7/qdeclarativeextensionplugin.html. Dobbiamo implementare la funzione ereditata, &quot;registerTypes()&quot;:http://doc.qt.nokia.com/4.7/qdeclarativeextensionplugin.html#registerTypes. Il file ''dialogPlugin.cpp'' si prenta cosi:


La classe Directory usa il sistema meta-oggetto di Qt per registrare le proprietà di cui ha bisogno per realizzare la gestione dei file. La classe Directory è esportata come plugin e usabile in <span class="caps">QML</span> come un elemento Directory. Ciascuna delle proprietà elencate che utilizza la macro [http://doc.qt.nokia.com/4.7/qobject.html#Q_PROPERTY Q_PROPERTY] ''[doc.qt.nokia.com]'' è una proprietà <span class="caps">QML</span>.
<code><br /> DialogPlugin.cpp:


Q_PROPERTY dichiara una proprietà, così come le sue funzioni di lettura e scrittura nel sistema meta-oggetto di Qt. Per esempio la proprietà ''filename'', di tipo [http://doc.qt.nokia.com/4.7/qstring.html QString] ''[doc.qt.nokia.com]'', è leggibile usando la funzione ''filename()'' e scrivibile usando la funzione ''setFilename()''. Inoltre. c’è un segnale associato alla proprietà ''filename'' chiamato ''filenameChanged()'', che è emesso quando la proprietà cambia. Le funzioni di lettura e scrittura sono dichiarate pubbliche nel file header.
#include &quot;dialogPlugin.h&amp;quot;<br /> #include &quot;directory.h&amp;quot;<br /> #include &quot;file.h&amp;quot;<br /> #include &lt;QtDeclarative/qdeclarative.h&amp;gt;


Allo stesso modo, abbiamo le altre proprietà dichiarate ai loro usi. La proprietà ''filesCount'' indica il numero di file in una directory. La proprietà filename è settata sul nome del file corrente selezionato e il caricamento/salvattaggio del contenuto del dile è memorizzato nella proprietà ''fileContent''.
void DialogPlugin::registerTypes(const char '''uri){
<br /> qmlRegisterType&amp;lt;Directory&amp;gt;(uri, 1, 0, &quot;Directory&amp;quot;);<br /> qmlRegisterType&amp;lt;File&amp;gt;(uri, 1, 0,&quot;File&amp;quot;);<br /> }
<br /> Q_EXPORT_PLUGIN2(FileDialog, DialogPlugin);<br /></code>
<br />La funzione &quot;registerTypes()&quot;:http://doc.qt.nokia.com/4.7/qdeclarativeextensionplugin.html#registerTypes registra le nostre classi File e Directory in QML. Questa funzione necessità di un nome per la classe per il suo template, un numero di versione maggiore e minore e un nome per la nostre classi.
<br />Dovremmo esportare il plugin usando la macro &quot;Q_EXPORT_PLUGIN2&amp;quot;:http://doc.qt.nokia.com/4.7/qtplugin.html#Q_EXPORT_PLUGIN2#q-export-plugin2. Notate nel nostro file dialogPlugin.h, abbiamo messo la macro &quot;Q_OBJECT&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html#Q_OBJECT macro all'inizo della classe. Dobbiamo quindi lanciare qmake sul progetto per generare i necessari codici meta-oggetto di Qt.
<br />h4. Creare proprietà QML nella classi C++
<br />Possiamo creare degli elementi e delle proprietà QML usando C++ e il sistema meta-oggetto di Qt. Possiamo implementare delle proprietà usando gli slot e signal, per farli conoscere a Qt. Queste proprieta possono poi essere usate in QML.
<br />Per l'editor di testi, abbiamo bisogno di abilitare il caricamento e salvataggio dei files. Tipicamente, queste funzionalità sono contenute in un file dialog. Fortunatamente, possiamo usare &quot;QDir&amp;quot;:http://doc.qt.nokia.com/4.7/qdir.html, &quot;QFile&amp;quot;:http://doc.qt.nokia.com/4.7/qfile.html e &quot;QTextStream&amp;quot;:http://doc.qt.nokia.com/4.7/qtextstream.html per implementare la lettura delle cartelle e i flussi di input/output.
<br /><code><br />class Directory : public QObject{
<br /> Q_OBJECT
<br /> Q_PROPERTY(int filesCount READ filesCount CONSTANT)<br /> Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged)<br /> Q_PROPERTY(QString fileContent READ fileContent WRITE setFileContent NOTIFY fileContentChanged)<br /> Q_PROPERTY(QDeclarativeListProperty&amp;lt;File&amp;gt; files READ files CONSTANT )
<br /> …<br /></code>
<br />La classe Directory usa il sistema meta-oggetto di Qt per registrare le proprietà di cui ha bisogno per realizzare la gestione dei file. La classe Directory è esportata come plugin e usabile in QML come un elemento Directory. Ciascuna delle proprietà elencate che utilizza la macro &quot;Q_PROPERTY&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html#Q_PROPERTY è una proprietà QML.
<br />Q_PROPERTY dichiara una proprietà, così come le sue funzioni di lettura e scrittura nel sistema meta-oggetto di Qt. Per esempio la proprietà ''filename'', di tipo &quot;QString&amp;quot;:http://doc.qt.nokia.com/4.7/qstring.html, è leggibile usando la funzione ''filename()'' e scrivibile usando la funzione ''setFilename()''. Inoltre. c'è un segnale associato alla proprietà ''filename'' chiamato ''filenameChanged()'', che è emesso quando la proprietà cambia. Le funzioni di lettura e scrittura sono dichiarate pubbliche nel file header.
<br />Allo stesso modo, abbiamo le altre proprietà dichiarate ai loro usi. La proprietà ''filesCount'' indica il numero di file in una directory. La proprietà filename è settata sul nome del file corrente selezionato e il caricamento/salvattaggio del contenuto del dile è memorizzato nella proprietà ''fileContent''.
<br /><code><br /> Q_PROPERTY(QDeclarativeListProperty&amp;lt;File&amp;gt; files READ files CONSTANT )<br /></code><br />La proprietà ''files'' list è una lista di tutti i file filtrati nella directory. La classe ''Directory'' è implementata per filtrare i file non validi; solo i file con estensione .txt sono validi. Inoltre, &quot;QLists&amp;quot;:http://doc.qt.nokia.com/4.7/qlist.html può essere utilizzata nei file QML dichiarandoli come &quot;QDeclarativeListProperty&amp;quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html in C+''. L'oggetto template deve ereditare da un &quot;QObject&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html, quindi, la classe File deve anche ereditare da QObject. Nella classe ''Directory'', l'elenco di oggetti File che è memorizzato in un Qlist chiamato ''m_fileList''.
<br /><code><br /> class File : public QObject{
<br /> Q_OBJECT<br /> Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
<br /> …<br /> };<br /></code>
<br />Le proprietà possono quindi essere utilizzate in QML come parte del elemento della proprietà Directory. Notate che non abbiamo bisogno di creare un identificatore id nel nostro codice C.
<br /><code><br /> Directory{<br /> id: directory
<br /> filesCount<br /> filename<br /> fileContent<br /> files
<br /> files[0].name<br /> }<br /></code>
<br />Siccome QML usa la sintassi e la struttura Javascript, possiamo scorrere l'elenco dei file e recuperare le sue proprietà. Per recuperare il nome del primo file, chiameremo ''files[0].name''.
<br />Le regolari funzioni C''+ sono accessibili anche da QML. Il caricamento e salvataggio implementati in C++ sono dichiarati usando la macro &quot;Q_INVOKABLE&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html#Q_INVOKABLE. Altrimenti, possiamo dichiarare le funzioni cme slot e saranno accessibili da QML.
<br /><code><br />In Directory.h:
<br /> Q_INVOKABLE void saveFile&amp;amp;#40;&amp;#41;;<br /> Q_INVOKABLE void loadFile&amp;amp;#40;&amp;#41;;<br /></code>
<br />La classe ''Directory'' deve inoltre notificare agli altri oggetti ogni volta che cambia il contenuto della directory. Questa funzione viene eseguita utilizzando un segnale. Come accennato in precedenza, i segnali QML devono avere un gestore corrispondente con prefisso i loro nomi. Il segnale è chiamato ''directoryChanged'' e viene emesso quando c'è un aggiornamento delal directory. L'aggiornamento semplicemente ricarica il contenuto della directory e aggiorna la lista dei files validi nella directory. Gli oggetti QML possono essere notificati collegando un azione al segnale ''onDirectoryChanged''.
<br />La lista di proprietà deve essere ulteriormente esplorata. Questo perché le proprietà list utilizzano delle chiamate per accedere e modificare il contenuto dell'elenco. La proprietà list è di tipo ''QDeclarativeListProperty&amp;lt;File&amp;gt;''. Ogni volta che si accede alla lista, la funzione di accesso deve restituire un ''QDeclarativeListProperty&amp;lt;File&amp;gt;''. Il template File, ha bisogno di derivare da un QObject. Inoltre, per creare &quot;QDeclarativeListProperty&amp;quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html, la lista di accesso e modifica devono essere passati al construttore come puntatori a funzione. La lista, in questo caso QList, deve anche essere una lista di puntatori a files.
<br />Il costruttore &quot;QDeclarativeListProperty&amp;quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html e l'implementazione della ''Directory'':
<br /><code><br /> QDeclarativeListProperty ( QObject''' object, void * data, AppendFunction append, CountFunction count = 0, AtFunction at = 0, ClearFunction clear = 0 )<br /> QDeclarativeListProperty&amp;lt;File&amp;gt;( this, &amp;m_fileList, &amp;appendFiles, &amp;filesSize, &amp;fileAt, &amp;clearFilesPtr );<br /></code>


La proprietà ''files'' list è una lista di tutti i file filtrati nella directory. La classe ''Directory'' è implementata per filtrare i file non validi; solo i file con estensione .txt sono validi. Inoltre, [http://doc.qt.nokia.com/4.7/qlist.html QLists] ''[doc.qt.nokia.com]'' può essere utilizzata nei file <span class="caps">QML</span> dichiarandoli come [http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html QDeclarativeListProperty] ''[doc.qt.nokia.com]'' in C++. L’oggetto template deve ereditare da un [http://doc.qt.nokia.com/4.7/qobject.html QObject] ''[doc.qt.nokia.com]'', quindi, la classe File deve anche ereditare da QObject. Nella classe ''Directory'', l’elenco di oggetti File che è memorizzato in un Qlist chiamato ''m_fileList''.
Il costruttore passa dei puntatori alla funzione che li accoda alla lista, conta la lista, recupera l'oggetto usando un indice e svuota la lista. Solo la funzione di accodamento è obbligatoria. Si noti che il puntatore a funzione deve corrispondere alla definizione di &quot;AppendFunction&amp;quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html#AppendFunction-typedef, &quot;CountFunction&amp;quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html#CountFunction-typedef, &quot;AtFunction&amp;quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html#AtFunction-typedef, o &quot;ClearFunction&amp;quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html#ClearFunction-typedef.


Le proprietà possono quindi essere utilizzate in <span class="caps">QML</span> come parte del elemento della proprietà Directory. Notate che non abbiamo bisogno di creare un identificatore id nel nostro codice C++.
<code><br /> void appendFiles(QDeclarativeListProperty&amp;lt;File&amp;gt; * property, File * file)<br /> File* fileAt(QDeclarativeListProperty&amp;lt;File&amp;gt; * property, int index)<br /> int filesSize(QDeclarativeListProperty&amp;lt;File&amp;gt; * property)<br /> void clearFilesPtr(QDeclarativeListProperty&amp;lt;File&amp;gt; *property)<br /></code>


Le regolari funzioni C++ sono accessibili anche da <span class="caps">QML</span>. Il caricamento e salvataggio implementati in C++ sono dichiarati usando la macro [http://doc.qt.nokia.com/4.7/qobject.html#Q_INVOKABLE Q_INVOKABLE] ''[doc.qt.nokia.com]''. Altrimenti, possiamo dichiarare le funzioni cme slot e saranno accessibili da <span class="caps">QML</span>.
Per semplificare la nostra file dialog, la classe Directory filtra i files di testo non validi, che non hanno estensione .txt. Se un file non ha estensione .txt, non sarà visibile nella nostra file dialog. Inoltre, l'applicazione consente di verificare che i file salvati hanno estensione. ''Directory'' utilizza &quot;QTextStream&amp;quot;:http://doc.qt.nokia.com/4.7/qtextstream.html per leggere il file e per esportare il contenuto in un file.


La classe ''Directory'' deve inoltre notificare agli altri oggetti ogni volta che cambia il contenuto della directory. Questa funzione viene eseguita utilizzando un segnale. Come accennato in precedenza, i segnali <span class="caps">QML</span> devono avere un gestore corrispondente con prefisso i loro nomi. Il segnale è chiamato ''directoryChanged'' e viene emesso quando c’è un aggiornamento delal directory. L’aggiornamento semplicemente ricarica il contenuto della directory e aggiorna la lista dei files validi nella directory. Gli oggetti <span class="caps">QML</span> possono essere notificati collegando un azione al segnale ''onDirectoryChanged''.
Con il nostro elemento ''Directory'', possiamo recuperare i file come lista, conoscere quanti file ci sono nella directory dell'applicazione, ottenere il nome del file e il suo contenuto come stringhe, e notificare se ci sono cambiamenti nel contenuto della directory.
 
Per compilare il plugin, lanciamo ''qmake'' sul file di progetto ''cppPlugins.pro'', e lanciamo un ''make'' per compilare e trasferire il plugin nella directory dei plugins.


La lista di proprietà deve essere ulteriormente esplorata. Questo perché le proprietà list utilizzano delle chiamate per accedere e modificare il contenuto dell’elenco. La proprietà list è di tipo ''QDeclarativeListProperty&lt;File&gt;''. Ogni volta che si accede alla lista, la funzione di accesso deve restituire un ''QDeclarativeListProperty&lt;File&gt;''. Il template File, ha bisogno di derivare da un QObject. Inoltre, per creare [http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html QDeclarativeListProperty] ''[doc.qt.nokia.com]'', la lista di accesso e modifica devono essere passati al construttore come puntatori a funzione. La lista, in questo caso QList, deve anche essere una lista di puntatori a files.
==== Integrare il File Dialog nel file Menu ====


Il costruttore [http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html QDeclarativeListProperty] ''[doc.qt.nokia.com]'' e l’implementazione della ''Directory'':
Il nostro ''FileMenu'' deve visualizzare l'elemento ''FileDialog'', contenente la lista di files in una directory, consentendo all'utente di selezionarne uno cliccando sulla lista. Abbiamo bisogno di assegnare i pulsanti del salvataggio e caricamento alle loro rispettive azioni. Il file FileMenu contiene un input di testo editabile per consentire all'utente di inserire il nome di un file attraverso la tastiera.


Il costruttore passa dei puntatori alla funzione che li accoda alla lista, conta la lista, recupera l’oggetto usando un indice e svuota la lista. Solo la funzione di accodamento è obbligatoria. Si noti che il puntatore a funzione deve corrispondere alla definizione di [http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html#AppendFunction-typedef AppendFunction] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html#CountFunction-typedef CountFunction] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html#AtFunction-typedef AtFunction] ''[doc.qt.nokia.com]'', o [http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html#ClearFunction-typedef ClearFunction] ''[doc.qt.nokia.com]''.
L'elemento Directory è usato nel file ''FileMenu.qml'' e notifica all'elemento ''FileDialog'' che la directory ha aggiornato il suo contenuto. Questa notifica è eseguita dal gestore del signal ''onDirectoryChanged''.


Per semplificare la nostra file dialog, la classe Directory filtra i files di testo non validi, che non hanno estensione .txt. Se un file non ha estensione .txt, non sarà visibile nella nostra file dialog. Inoltre, l’applicazione consente di verificare che i file salvati hanno estensione. ''Directory'' utilizza [http://doc.qt.nokia.com/4.7/qtextstream.html QTextStream] ''[doc.qt.nokia.com]'' per leggere il file e per esportare il contenuto in un file.
<code><br /> In FileMenu.qml:


Con il nostro elemento ''Directory'', possiamo recuperare i file come lista, conoscere quanti file ci sono nella directory dell’applicazione, ottenere il nome del file e il suo contenuto come stringhe, e notificare se ci sono cambiamenti nel contenuto della directory.
Directory{<br /> id:directory<br /> filename: textInput.text<br /> onDirectoryChanged: fileDialog.notifyRefresh()<br /> }<br /></code>


Per compilare il plugin, lanciamo ''qmake'' sul file di progetto ''cppPlugins.pro'', e lanciamo un ''make'' per compilare e trasferire il plugin nella directory dei plugins.
Mantenendo con la semplicità della nostra applicazione, il filedialog sarà sempre visibile e non visualizzaremo file di testo non validi, che non hanno un estensione .txt.


====Integrare il File Dialog nel file Menu====
<code><br />In FileDialog.qml:


Il nostro ''FileMenu'' deve visualizzare l’elemento ''FileDialog'', contenente la lista di files in una directory, consentendo all’utente di selezionarne uno cliccando sulla lista. Abbiamo bisogno di assegnare i pulsanti del salvataggio e caricamento alle loro rispettive azioni. Il file FileMenu contiene un input di testo editabile per consentire all’utente di inserire il nome di un file attraverso la tastiera.
signal notifyRefresh()<br /> onNotifyRefresh: dirView.model = directory.files<br /></code>


L’elemento Directory è usato nel file ''FileMenu.qml'' e notifica all’elemento ''FileDialog'' che la directory ha aggiornato il suo contenuto. Questa notifica è eseguita dal gestore del signal ''onDirectoryChanged''.
L'elemento ''FileDialog'' visualizza il contenuto della directory leggendo le sue proprietà chiamate files. I files sono usati come modelli dell'elemento &quot;GridView&amp;quot;:http://doc.qt.nokia.com/4.7/qml-gridview.html, che visualizza gli oggetti in una griglia in accordo con il suo delegato. Il delegato gestisce l'aspetto del modello e il nostro file dialog semplicemente crea una griglia con un testo centrato nel mezzo. Cliccando sul nome del file si visualizzerà un rettangolo per evidenziare il nome del file. Il FileDialog è notificato ogni volta che il segnale ''notifyRefresh'' è emesso, ricaricando i files nella directory.


Mantenendo con la semplicità della nostra applicazione, il filedialog sarà sempre visibile e non visualizzaremo file di testo non validi, che non hanno un estensione .txt.
<code><br /> In FileMenu.qml:


L’elemento ''FileDialog'' visualizza il contenuto della directory leggendo le sue proprietà chiamate files. I files sono usati come modelli dell’elemento [http://doc.qt.nokia.com/4.7/qml-gridview.html GridView] ''[doc.qt.nokia.com]'', che visualizza gli oggetti in una griglia in accordo con il suo delegato. Il delegato gestisce l’aspetto del modello e il nostro file dialog semplicemente crea una griglia con un testo centrato nel mezzo. Cliccando sul nome del file si visualizzerà un rettangolo per evidenziare il nome del file. Il FileDialog è notificato ogni volta che il segnale ''notifyRefresh'' è emesso, ricaricando i files nella directory.
Button{<br /> id: newButton<br /> label: &quot;New&amp;quot;<br /> onButtonClick:{<br /> textArea.textContent = &quot;&quot;<br /> }<br /> }<br /> Button{<br /> id: loadButton<br /> label: &quot;Load&amp;quot;<br /> onButtonClick:{<br /> directory.filename = textInput.text<br /> directory.loadFile&amp;amp;#40;&amp;#41;<br /> textArea.textContent = directory.fileContent<br /> }<br /> }<br /> Button{<br /> id: saveButton<br /> label: &quot;Save&amp;quot;<br /> onButtonClick:{<br /> directory.fileContent = textArea.textContent<br /> directory.filename = textInput.text<br /> directory.saveFile&amp;amp;#40;&amp;#41;<br /> }<br /> }<br /> Button{<br /> id: exitButton<br /> label: &quot;Exit&amp;quot;<br /> onButtonClick:{<br /> Qt.quit()<br /> }<br /> }<br /></code>


Il nostro ''FileMenu'' può ora connette le sue rispettive azioni. Il ''saveButton'' trasferirà il testo dal ''TextEdit'' sulla proprietà ''fileContent'' della directory, poi copierà il nome dall’ input textedit. Finalmente, il pulsante chiamerà la funzione ''saveFile()'', salvando il file. Il pulsante ''loadButton'' ha una simile esecuzione. Inoltre, l’azione ''New'' svuoterà il contenuto del TextEdit.
Il nostro ''FileMenu'' può ora connette le sue rispettive azioni. Il ''saveButton'' trasferirà il testo dal ''TextEdit'' sulla proprietà ''fileContent'' della directory, poi copierà il nome dall' input textedit. Finalmente, il pulsante chiamerà la funzione ''saveFile&amp;amp;#40;&amp;#41;'', salvando il file. Il pulsante ''loadButton'' ha una simile esecuzione. Inoltre, l'azione ''New'' svuoterà il contenuto del TextEdit.


Inoltre, i pulsanti ''EditMenu'' sono collegati alle funzioni di ''TextEdit'' per copiare, incollare e selezionare tutto il testo nell’editor di testo.
Inoltre, i pulsanti ''EditMenu'' sono collegati alle funzioni di ''TextEdit'' per copiare, incollare e selezionare tutto il testo nell'editor di testo.


[[Image:qml-texteditor5_filemenu.png|editor di testo quasi completo]]
p=. [[Image:http://doc.qt.nokia.com/4.7/images/qml-texteditor5_filemenu.png|editor di testo quasi completo]]


===Completamento Editor di testi===
=== Completamento Editor di testi ===


[[Image:qml-texteditor5_newfile.png|editor di testi finito]]
p=. [[Image:http://doc.qt.nokia.com/4.7/images/qml-texteditor5_newfile.png|editor di testi finito]]


L’applicazione può funzionare come un semplice editor di testi, in grado di accettare il testo e salvarlo in un file. L’editor di testo può anche caricare un file e eseguire la manipolazione del testo.
L'applicazione può funzionare come un semplice editor di testi, in grado di accettare il testo e salvarlo in un file. L'editor di testo può anche caricare un file e eseguire la manipolazione del testo.

Revision as of 09:52, 24 February 2015

h1. Introduzione Alla Programmazione Con QML

Benvenuti nel mondo di QML, il linguaggio dichiarativo per la realizzazione di interfacce utente (UI, user interface).
In questa guida introduttiva, costruiremo un semplice editor di testo utilizzando QML. Dopo aver letto questa guida, dovresti essere pronto per sviluppare le tue applicazioni usando QML e Qt C+.
h2. QML per la creazione di UI
L'applicazione che svilupperemo sarà un semplice editor di testo e permetterà di caricare, salvare e modificare del testo. Questa introduzione è divisa in due parti. La prima parte si occupa dello sviluppo del layout e dei comportamenti dei componenti dell'applicazione tramite il linguaggio QML. La seconda, invece, tratta dell'implementazione delle funzioni di caricamento e salvataggio utilizzando Qt C. Grazie al "Qt's Meta-Object System&quot;:http://doc.qt.nokia.com/4.7/metaobjects.html, possiamo esporre le funzioni C+ come proprietà usate da elementi del linguaggio QML. Usando QML e Qt C+, possiamo separare efficacemente la logica del layout dalla logica riguardante le funzionalità dell'applicazione.
p=. Immagine editor di testi
Per eseguire il codice QML dell'esempio, è sufficiente passare come argomento allo strumento "qmlviewer&quot;:http://doc.qt.nokia.com/4.7/qmlviewer.html i files QML. La seguente introduzione è pensata per quei lettori che hanno almeno una minima conoscenza della procedura per la compilazione di applicazioni in Qt.
Capitoli:
# Definizione di pulsanti e menu
# Implementare barra dei menu
# Costruire un editor di testo
# Decorare l'editor di testo
# Estendere QML attraverso Qt C+

Definizione di pulsanti e menu

Componenti base - Pulsante

Iniziamo il nostro editor di testi costruendo un pulsante. Un pulsante è costituito da un'area sensibile al mouse e da un'etichetta. I pulsanti eseguono un azione alla pressione da parte dell'utente.
In QML, l'oggetto visuale di base è il "Rectangle&quot;:http://doc.qt.nokia.com/4.7/qml-rectangle.html. Il Rectangle ha le proprietà per controllare l'aspetto e la posizione degli elementi.

import Qt 4.7

Rectangle{<br /> id:simplebutton

color: &quot;grey&amp;quot;<br /> width: 400; height: 400

Text {<br /> id: buttonLabel<br /> text: &quot;button label&amp;quot;<br /> anchors.centerIn:parent<br /> }<br />}

Innanzitutto, la riga import Qt 4.7 abilita il tool qmlviewer all'importazione di elementi QML. Questa linea deve essere presente in ogni file QML. Si noti che la versione dei moduli di Qt è inclusa nella dichiarazione.

Il Rectangle ha un identificatore univoco, simplebutton, che è associato alla proprietà id. Le properità del Rectangle sono specificate definendone prima il nome e, dopo il simbolo : (due punti), il valore. Nel codice di esempio, il colore grey è legato alla proprietà color del Rectangle. Stessa cosa per larghezza e altezza (width e height).

L'elemento "Text&quot;:http://doc.qt.nokia.com/4.7/qml-text.html è un campo di testo non editabile. Lo chiameremo buttonLabel. Per impostare il contenuto del campo di testo, assoceremo un valore alla sua proprietà text. L'etichetta è contenuta all'interno del rectangle, e per centrarla in mezzo, colleghiamo gerarchicamente le anchors (ancore) dell’elemento Text al suo genitore, che nel nostro caso si chiama simplebutton.
Ogni ancora può essere collegata alle ancore di altri elementi; in questo modo si semplifica la definizione della disposizione reciproca degli elementi.

Salveremo il tutto come SimpleButton.qml. Lanciando qmlviewer con il nome del file creato come argomento, verrà mostrato a schermo un rettangolo grigio con un'etichetta di testo.

p=. pulsante grigio con etichetta testo

Per implementare l'evento click sul pulsante, possiamo usare la gestione degli eventi di QML. La gestione eventi di QML è molto simile al meccanismo "signal e slot&quot;:http://doc.qt.nokia.com/4.7/signalsandslots.html di Qt. Un segnale sarà emesso e il relativo slot connesso sarà chiamato.

Rectangle{<br /> id:simplebutton<br /> 

MouseArea{<br /> id: buttonMouseArea

anchors.fill: parent //ancora tutti i lati della MouseArea ai lati del rettangolo<br /> //onClicked gestisce click del mouse validi<br /> onClicked: console.log(buttonLabel.text + &quot; clicked&amp;quot; )<br /> }<br /> }

Aggiungiamo un elemento "MouseArea&quot;:http://doc.qt.nokia.com/4.7/qml-mousearea.html nel nostro componente simplebutton. Gli elementi MouseArea descrivono l'area interattiva dove i movimenti del mouse sono rilevati. Per il nostro pulsante, ancoriamo l'intera MouseArea al suo genitore (parent), il simplebutton. La sintassi anchors.fill è un modo per accedere ad una specifica proprietà chiamata fill all'interno di un gruppo di proprietà denominate anchors. QML utilizza "layouts basati su ancore&quot;:http://doc.qt.nokia.com/4.7/qml-anchor-layout.html, dove gli elementi possono ancorarsi ad altri elementi, creando layout robusti e flessibili.

La MouseArea ha molti gestori di segnali che possono essere chiamati durante i movimenti del mouse all'interno dei limiti specificati. Uno di questi è onClicked ed è invocato ogni qualvolta viene cliccato un pulsante valido del mouse; il pulsante di default è quello sinistro. Possiamo legare azioni al gestore onClicked. Nel nostro esempio, console.log() visualizza testo ogni volta che viene cliccata la MouseArea. La funzione console.log() è uno strumento utile per scopi di debugging e, in generale, per visualizzare del testo in output.

Il codice in SimpleButton.qml è sufficiente per mostrare un bottone sullo schermo e visualizzare del testo ogni volta che viene cliccato con il mouse.

<br />Rectangle {<br /> id:Button<br /> 

property color buttonColor: &quot;lightblue&amp;quot;<br /> property color onHoverColor: &quot;gold&amp;quot;<br /> property color borderColor: &quot;white&amp;quot;

signal buttonClick()<br /> onButtonClick: {<br /> console.log(buttonLabel.text + &quot; clicked&amp;quot; )<br /> }

MouseArea{<br /> onClicked: buttonClick()<br /> hoverEnabled: true<br /> onEntered: parent.border.color = onHoverColor<br /> onExited: parent.border.color = borderColor<br /> }

// determina il colore del bottone utilizando l'operatore condizionale<br /> color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor<br />}<br />

Un pulsante completamente funzionante è Button.qml. Il codice visualizzato in questo articolo omette alcune parti, denotate da "…", poiché sono già state introdotte nella sezione precedente o comunque sono irrilevanti ai fini della discussione di questo specifico codice.

Per dichiarare proprietà personalizzate si utilizza la sintassi: proprietà tipo nome. Nel codice, viene dichiarata la proprietà buttonColor, di tipo color, e vincolata al valore "lightblue". La proprietà buttonColor è utilizzata successivamente in un'operazione condizionale per determinare il colore di riempimento del bottone. Si noti che per assegnare dei valori alle proprietà è possibile utilizzare il segno uguale &quot;=&quot;oppure il segno due punti &quot;:&quot;. Le proprietà personalizzate permettono di rendere accessibili elementi interni all’elemento Rectangle, anche dall’esterno del suo campo di visibiltà. Esistono diversi "tipi QML&quot;:http://doc.qt.nokia.com/4.7/qdeclarativebasictypes.html di base come int, string, real, ma anche un tipo generico chiamato variant.

Legando i gestori dei segnali onEntered ed onExited ai colori, il colore del bordo del pulsante diventa giallo quando il mouse si sposta sopra di esso e ritorna del colore pecedente quando il mouse esce dalla MouseArea.

Un segnale buttonClick() è dichiarato in Button.qml inserendo la parola chiave signal davanti al nome del segnale. Per ogni segnale vengono create automaticamente le relative funzioni di gestione, i cui nomi iniziano con il prefisso on. Come risultato si ha che il gestore di buttonClick è onButtonClick. All'onButtonClick è successivamente assegnata un'azione da svolgere. Nel nostro esempio, il gestore del mouse onClicked chiamerà semplicemente onButtonClick, il quale ha il compito di visualizzare del testo. onButtonClick permette ad oggetti esterni di accedere facilmente alla MouseArea del Button. Inoltre, gli elementi possono avere dichiarate più di una MouseArea, ed avere il segnale buttonClick permette di distinguere meglio i diversi gestori di segnali delle varie MouseArea.

Ora abbiamo le conoscenze essenziali per implementare in QML oggetti che possono gestire i principali movimenti del mouse. Abbiamo creato un'etichetta Text all'interno di un Rectangle, personalizzato le sue proprietà ed implementato dei comportamenti che rispondano ai movimenti del mouse. Questa idea di base della creazione di elementi all’interno di altri elementi, si ripresenterà nello sviluppo di tutta l'applicazione di esempio.

Il pulsante realizzato non è molto utile se non viene usato come componente per eseguire una qualche azione. Nella prossima sezione creeremo un menu contenente alcuni di questi pulsanti.

p=. Pulsante grigio chiaro con all'interno un'etichetta

Creazione della pagina del menu

Fino ad ora abbiamo visto come creare elementi ed assegnare comportamenti all'interno di file QML. In questa sezione, scopriremo come importare elementi QML e come riutilizzare alcuni componenti creati per costruire altri componenti.

Un menu mostra il contenuto di una lista i cui elementi hanno la capacità di compiere un'azione. In QML possiamo ottnere un menu in vari modi. Prima di tutto creeremo un menu contenente dei pulsanti a cui faremo eseguire azioni differenti. Il codice del menu è in FileMenu.qml.

<br />import Qt 4.7 //Importa il modulo Qt QML principale<br />import &quot;folderName&amp;quot; //Importa il contenuto della cartella<br />import &quot;script.js&amp;quot; as Script //Importa un file javascript e lo chiama Script<br />

La sintassi riportata mostra come utilizzare la parola chiave import. Ciò è richiesto per utilizzare file "JavaScript&quot;:https://developer.mozilla.org/en/JavaScript o QML che non sono nella stessa cartella. Siccome Button.qml si trova nella stessa cartella di FileMenu.qml, non è necessario importare esplicitamente il file Button.qml per poterlo usare, ma possiamo creare direttamente un elemento Button dichiarando Button{}, come è stato fatto per Rectangle{}.

<br />In FileMenu.qml:

Row{<br /> anchors.centerIn: parent<br /> spacing: parent.width/6

Button{<br /> id: loadButton<br /> buttonColor: &quot;lightgrey&amp;quot;<br /> label: &quot;Load&amp;quot;<br /> }<br /> Button{<br /> buttonColor: &quot;grey&amp;quot;<br /> id: saveButton<br /> label: &quot;Save&amp;quot;<br /> }<br /> Button{<br /> id: exitButton<br /> label: &quot;Exit&amp;quot;<br /> buttonColor: &quot;darkgrey&amp;quot;

onButtonClick: Qt.quit()<br /> }<br /> }<br />

In FileMenu.qml abbiamo dichiarato tre elementi Button. Essi sono definiti all'interno di un elemento di tipo Row, un elemento di posizionamento che ha lo scopo di collocare i suoi figli lungo una riga orizzontale. La dichiarazione di Button si trova nel file Button.qml, lo stesso che abbiamo utilizzato nella sezione precedente. Le impostazioni delle proprietà possono essere dichiarate all'interno della dichiarazione del pulsante; in questo modo si sovrascrivono le proprietà impostate in Button.qml. Quando cliccato, il pulsante chiamato exitButton chiuderà l'applicazione. Si noti che il gestore di segnale onButtonClick in Button.qml sarà chiamato in aggiunta al gestore onButtonClick in exitButton.

p=. Immagine menu File

La dichiarazione dell'elemento di tipo Row è fatta all'interno di un Rectangle, creando un contenitore a forma di rettangolo per la riga di pulsanti. Il rettangolo aggiuntivo permette di aver un modo indiretto di organizzare la riga di pulsanti all'interno del menu.

La dichiarazione del menu di editing è molto simile a quella precedente. Questo menù è composto da pulsanti con le etichette Copy, Paste e Select All.

p=. Immagine menu Edit

Forti della conoscenza acquisita sull'importazione e sulla personalizzazione dei componenti, possiamo ora combinare queste pagine di menu per creare una singola barra dei menu, composta da pulsanti per selezionare il menu, e vedere come strutturare i dati usando QML.

Implementare la barra dei menu

Il nostro editor di testi necessità di un modo per visualizzare i menu tramite una barra dei menu. La barra dei menu proporrà i diversi menu attraverso cui l'utente potrà navigare. Per il cambio del menu occorrerà una struttura più complessa della semplice visualizzazione su una riga. QML utilizza modelli e viste per gestire e visualizzare i dati strutturati.

Usare la struttura modello-vista

QML dispone di diverse "viste&quot;:http://doc.qt.nokia.com/4.7/qdeclarativemodels.html per visualizzare i "modelli&quot;:http://doc.qt.nokia.com/4.7/qdeclarativemodels.html. La nostra barra dei menu visualizzerà i menu in una lista, con un'intestazione che mostrerà i nomi dei menu su una riga. L'elenco dei menu è dichiarato all'interno di un VisualItemModel. L'elemento "VisualItemModel&quot;:http://doc.qt.nokia.com/4.7/qml-visualitemmodel.html contiene gli oggetti che hanno già delle viste, come l'oggetto Rectangle e gli altri elementi dell'interfaccia. Altri tipi di modelli, come l'elemento "ListModel&quot;:http://doc.qt.nokia.com/4.7/qml-listmodel.html, necessitano di un delegato per visualizzare i propri dati.

Dichiariamo quindi due elementi visuali nel menuListModel, il FileMenu e EditMenu, li personalizziamo e li visualizziamo usando il "ListView&quot;:http://doc.qt.nokia.com/4.7/qml-listview.html. Il file MenuBar.qml contiene le dichiarazioni QML e un semplice menu di modifica è definito nel file EditMenu.qml.

 VisualItemModel{<br /> id: menuListModel<br /> FileMenu{<br /> width: menuListView.width<br /> height: menuBar.height<br /> color: fileColor<br /> }<br /> EditMenu{<br /> color: editColor<br /> width: menuListView.width<br /> height: menuBar.height<br /> }<br /> }

L'elemento ListView visualizza un modello attraverso il suo elemento delegato. Il delegato può definire che gli elementi del modello da visualizzare siano disposti in una riga o in una griglia. Il nostro menuListModel ha già degli oggetti visibili, quindi non abbiamo bisogno di dichiarare un delegato.

<br /> ListView{<br /> id: menuListView

//Le anchors sono settate per adattarsi alla finestra<br /> anchors.fill:parent<br /> anchors.bottom: parent.bottom<br /> width:parent.width<br /> height: parent.height

//Il model contiene i dati<br /> model: menuListModel

//Controlla il movimento del passaggio tra i menu<br /> snapMode: ListView.SnapOneItem<br /> orientation: ListView.Horizontal<br /> boundsBehavior: Flickable.StopAtBounds<br /> flickDeceleration: 5000<br /> highlightFollowsCurrentItem: true<br /> highlightMoveDuration:240<br /> highlightRangeMode: ListView.StrictlyEnforceRange<br /> }

Inoltre, ListView eredita da "Flickable&quot;:http://doc.qt.nokia.com/4.7/qml-flickable.html, rendendo la lista reattiva al trascinamento del mouse ed a altre gestures. L'ultima parte di codice imposta la proprietà Flickable per creare dei movimenti di ribaltamento alla nostra vista. In particolare, la proprietà highlightMoveDuration cambia la durata della transizione: un valore più alto di highlightMoveDuration renderà il passaggio tra i menu più lento.

Il ListView gestisce gli elementi del modello attraverso un index (indice) e ogni elemento visuale nel modello è accessibile tramite questo indice, secondo l'ordine di dichiarazione. Cambiando il currentIndex cambieremo l'elemento evidenziato nella Listview. L'intestazione della barra dei menu semplifica questo effetto. Ci sono due pulsanti sulla stessa riga, quando cliccati entrambi cambiano il menu corrente. Il pulsante fileButton quando cliccato cambia il menu corrente con FileMenu; l'indice diventa 0 perchè FileMenu è il primo elemento dichiarato nel menuListModel. Analogamente il pulsante editButton sostituisce il menu corrente con EditMenu.

Il rettangolo dell'etichetta labelList ha un valore di z settato a 1, e sarà quindi visualizzata davanti alla barra dei menu. Gli oggetti con un valore di z maggiori saranno visualizzati in primo piano rispetto a quelli con un valore di z inferiore. Il valore di default di z è 0.

<br /> Rectangle{<br /> id: labelList<br /> <br /> z: 1<br /> Row{<br /> anchors.centerIn: parent<br /> spacing:40<br /> Button{<br /> label: &quot;File&amp;quot;<br /> id: fileButton<br /> <br /> onButtonClick: menuListView.currentIndex = 0<br /> }<br /> Button{<br /> id: editButton<br /> label: &quot;Edit&amp;quot;<br /> <br /> onButtonClick: menuListView.currentIndex = 1<br /> }<br /> }<br /> }

La barra dei menu appena creata potrà essere sfogliata per accedere ai menu oppure si può semplicemente cliccare sui nomi dei menu. Il cambiamento dei menu è intuitivo e reattivo.

p=. barra dei menu

Costruire un editor di testo

Dichiarare un'area di testo

Il nostro editor di testo non potrà mai essere un vero editor di testo finché non inseriremo un area di testo modificabile. L'elemento "TextEdit&quot;:http://doc.qt.nokia.com/4.7/qml-textedit.html permette la dichiarazione di un componente per la modifica di testo multilinea. TextEdit è diverso dall'elemento "Text&quot;:http://doc.qt.nokia.com/4.7/qml-text.html, che non consente all'utente di modificare direttamente il testo.

<br />TextEdit{<br /> id: textEditor<br /> anchors.fill:parent<br /> width:parent.width; height:parent.height<br /> color:&quot;midnightblue&amp;quot;<br /> focus: true

wrapMode: TextEdit.Wrap

onCursorRectangleChanged: flickArea.ensureVisible(cursorRectangle)<br /> }

L'editor contiene proprietà per impostare il colore del testo e per farlo andare a capo. L'area di testo TextEdit è contenuta all'interno di un'area scorrevole che farà scorrere il testo se il cursore si trova al di fuori dell'area visibile. La funzione ensureVisible() controlla se il rettangolo del cursore è fuori dai confini visibili e, nel caso, sposta opportunamente l'area di testo. QML usa la sintassi Javascript per i suoi scripts, e, come accennato in precedenza, i file Javascript possono essere importati e utilizzati all'interno di un file QML.

<br /> function ensureVisible®{<br /> if (contentX &gt;= r.x)<br /> contentX = r.x;<br /> else if (contentX+width &lt;= r.x+r.width)<br /> contentX = r.x+r.width-width;<br /> if (contentY &gt;= r.y)<br /> contentY = r.y;<br /> else if (contentY+height &lt;= r.y+r.height)<br /> contentY = r.y+r.height-height;<br /> }

Combinare i componenti per l'editor di testi

Ora siamo pronti per creare il layout del nostro editor di testo mediante QML. L'editor di testo ha due componenti: la barra dei menu e l'area di testo. QML ci permette di riutilizzare i componenti, rendendo il codice più semplice, attraverso l'importazione e la personalizzazione degli stessi quando necessario. Il nostro editor di testo divide la finestra in due parti, un terzo dello schermo è dedicato alla barra dei menu ed i rimanenti due terzi della schermata sono destinati alla visualizzazione dell'area di testo. La barra dei menu viene visualizzata in primo piano rispetto a qualsiasi altro elemento.

 Rectangle{

id: screen<br /> width: 1000; height: 1000

//Lo schermo è diviso in MenuBar e TextArea. La MenuBar occupa 1/3 dello schermo<br /> property int partition: height/3

MenuBar{<br /> id:menuBar<br /> height: partition<br /> width:parent.width<br /> z: 1<br /> }

TextArea{<br /> id:textArea<br /> anchors.bottom:parent.bottom<br /> y: partition<br /> color: &quot;white&amp;quot;<br /> height: partition*2<br /> width:parent.width<br /> }<br /> }

Tramite l'importazione di componenti riutilizzabili, il codice del nostro editor di testo appare molto più semplice. Possiamo quindi personalizzare l'applicazione principale, senza preoccuparci delle proprietà che abbiamo già definito prima. Usando questo approccio, i layout delll'applicazione ed i componenti dell'interfaccia grafica possono essere creati ed assemblati più facilmente.

p=. editor di testi

Decorare l'editor di testo

Implementare un interfaccia a scomparsa

Il nostro editor di testo appare semplice, ma possiamo abbellirlo. Utilizzando QML possiamo dichiarare delle transizioni per animarlo. La nostra barra del menu occupa un terzo dello schermo, sarebbe carino se apparisse solo quando lo vogliamo.

A tale scopo possiamo aggiungere un elemento di interfaccia (drawer) che si occuperà di contrarre o espandere la barra dei menu quando viene cliccata. Nella nostra implementazione abbiamo un sottile rettangolo che risponde ai click del mouse. Il drawer, così come l'applicazione, ha due stati: aperto (DRAWER_OPEN) e chiuso (DRAWER_CLOSED). L'elemento drawer è una sottile striscia rettangolare al cui interno è presente un elemento "immagine&quot;:http://doc.qt.nokia.com/4.7/qml-image.html che definisce un'icona a forma di freccia centrata all'interno dell'area. Il drawer assegna uno stato, con identificativo screen, all'intera applicazione ogni volta che l'utente clicca la MouseArea.

Rectangle{<br /> id:drawer<br /> height:15

Image{<br /> id: arrowIcon<br /> source: &quot;images/arrow.png&amp;quot;<br /> anchors.horizontalCenter: parent.horizontalCenter<br /> }

MouseArea{<br /> id: drawerMouseArea<br /> anchors.fill:parent<br /> onClicked:{<br /> if (screen.state  &amp;quot;DRAWER_CLOSED&amp;quot;)&amp;#123;
                     screen.state = &amp;quot;DRAWER_OPEN&amp;quot;
                 &amp;#125;
                 else if (screen.state  &quot;DRAWER_OPEN&amp;quot;){<br /> screen.state = &quot;DRAWER_CLOSED&amp;quot;<br /> }<br /> }<br /> <br /> }<br /> }<br />

Uno stato è semplicemente un'insieme di configurazioni predefinite e si dichiara tramite un elemento "State&quot;:http://doc.qt.nokia.com/4.7/qml-state.html. Una lista di stati può essere collegata alla proprietà states. Nella nostra applicazione i due stati sono chiamati DRAWER_CLOSED e DRAWER_OPEN. La configurazione dei componenti è definita negli elementi "PropertyChanges&quot;:http://doc.qt.nokia.com/4.7/qml-propertychanges.html. Nello stato DRAWER_OPEN quattro elementi riceveranno modifiche alle loro proprietà. Il primo, la menuBar, cambia la proprietà y in 0. Similmente, la textArea si abbasserà in una nuova posizione quando lo stato è DRAWER_OPEN. La textArea, il drawer e la sua icona subiranno cambiamenti delle loro proprietà per adeguarsi allo stato corrente.

states:[<br /> State {<br /> name: &quot;DRAWER_OPEN&amp;quot;<br /> PropertyChanges { target: menuBar; y: 0}<br /> PropertyChanges { target: textArea; y: partition + drawer.height}<br /> PropertyChanges { target: drawer; y: partition}<br /> PropertyChanges { target: arrowIcon; rotation: 180}<br /> },<br /> State {<br /> name: &quot;DRAWER_CLOSED&amp;quot;<br /> PropertyChanges { target: menuBar; y:<s>height; }<br /> PropertyChanges { target: textArea; y: drawer.height; height: screen.height</s> drawer.height }<br /> PropertyChanges { target: drawer; y: 0 }<br /> PropertyChanges { target: arrowIcon; rotation: 0 }<br /> }<br /> ]<br />

Le variazioni tra uno stato e l'altro sono brusche, perciò necessitano di transizioni più dolci. Le transizioni tra gli stati sono definite utilizzando l'elemento "Transition&quot;:http://doc.qt.nokia.com/4.7/qml-transition.html, che può essere legato alla proprietà transitions di un elemento. il nostra editor di testo effettua transizioni quando lo stato diventa DRAWER_OPEN oppure DRAWER_CLOSED. È importante sottolineare che le transizioni necessitano di uno stato di partenza (from) e di uno di arrivo (to), tuttavia, nel nostro caso, possiamo utilizzare il simbolo jolly * per indicare che la transizione si applica a tutti i cambiamenti di stato.

Durante le transizioni possiamo assegnare delle animazioni ai cambiamenti di proprietà. La nostra menuBar cambia posizione da y:0 a y:-partition: è possibile animare questa transizione utilizzando l'elemento "NumberAnimation&quot;:http://doc.qt.nokia.com/4.7/qml-numberanimation.html. Definiamo che le proprietà dell'oggetto si animino per un certo periodo con un andamento definito da una certa curva. Una curva di andamento controlla la progressione dell'animazione, interpolando i comportamenti durante la variazione di stato. L'evoluzione della curva scelta è "Easing.Out.Quint&quot;:http://doc.qt.nokia.com/4.7/qml-propertyanimation.html#easing.type-prop che rallenta i movimenti verso la fine dell'animazione. E' possibile approfondire l'argomento leggendo l'articolo "QML’s Animation&quot;:http://doc.qt.nokia.com/4.7/qdeclarativeanimation.html.

transitions: [<br /> Transition {<br /> to: &quot;*&quot;<br /> NumberAnimation { target: textArea; properties: &quot;y, height&amp;quot;; duration: 100; easing.type:Easing.OutExpo }<br /> NumberAnimation { target: menuBar; properties: &quot;y&amp;quot;; duration: 100; easing.type: Easing.OutExpo }<br /> NumberAnimation { target: drawer; properties: &quot;y&amp;quot;; duration: 100; easing.type: Easing.OutExpo }<br /> }<br /> ]<br />

Un altro modo per animare variazioni dei valori delle proprietà è dichiarando un elemento "Behaviour&quot;:http://doc.qt.nokia.com/4.7/qml-behavior.html. Una transizione avviene solo durante cambi di stato e Behaviour può impostare un'animazione per una modifica generica della proprietà. Nell'editor di testo, l'icona freccia ha un NumberAnimation che anima la sua proprietà rotation ad ogni cambiamento.

In TextEditor.qml:

Behavior{<br /> NumberAnimation{property: &quot;rotation&amp;quot;;easing.type: Easing.OutExpo }<br /> }<br />

Grazie alla conoscenza di stati ed animazioni, siamo ora in grado di migliorare l'aspetto dei nostri componenti. In Button.qml possiamo aggiungere modifiche alle proprietà scale e color quando il bottone viene premuto. I tipi colore si animano utilizzando ColorAnimation, mentre i tipi numerici con NumberAnimation. La sintassi on nomeProprietà mostrata sotto semplifica il lavoro quando si lavora su di una singola proprietà.

In Button.qml:<br /> 

color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor<br /> Behavior on color { ColorAnimation{ duration: 55} }

scale: buttonMouseArea.pressed ? 1.1 : 1.00<br /> Behavior on scale { NumberAnimation{ duration: 55} }<br />

Inoltre, possiamo migliorare l'aspetto dei componenti QML aggiungendo effetti di colore, come sfumature ed effetti di trasparenza. Dichiarando un elemento "Gradient&quot;:http://doc.qt.nokia.com/4.7/qml-gradient.html si sovrascrive la proprietà color dell'elemento. E' possibile definire un colore all'interno della sfumatura utilizzando l'elemento "GradientStop&quot;:http://doc.qt.nokia.com/4.7/qml-gradientstop.html. La sfumatura è valorrizata utilizzando una scala tra 0,0 e 1,0.

In MenuBar.qml<br /> gradient: Gradient {<br /> GradientStop { position: 0.0; color: &quot;#8C8F8C&amp;quot; }<br /> GradientStop { position: 0.17; color: &quot;#6A6D6A&amp;quot; }<br /> GradientStop { position: 0.98;color: &quot;#3F3F3F&amp;quot; }<br /> GradientStop { position: 1.0; color: &quot;#0e1B20&amp;quot; }<br /> }<br />

Il gradiente è usato dalla barra del menu per simulare l'effetto di profondità. Il primo colore inizia a 0.0 e l'ultimo termina a 1.0.

Prossimi passi

Abbiamo terminato di costruire l'interfaccia utente di un semplice editor di testo. Proseguendo, completata l’interfaccia utente, possiamo implementare la logica dell'applicazione utilizzando Qt e C++ standard. QML funziona bene come strumento di prototipazione, separando efficacemente la logica dell'applicazione dal progetto dell'interfaccia utente.

p=. Interfaccia editor quasi conclusa

Estendere QML attraverso Qt C++

Ora che abbiamo completato il layout del nostro editor di testi, possiamo implementare le funzionalità in C+. Usando il QML con C+ abbiamo la possibilità di creare la logica della nostra applicazione attraverso Qt. Possiamo creare dei contenuti QML in un applicazione C++ usando le "classi dichiarative Qt&quot;:http://doc.qt.nokia.com/4.7/qtbinding.html e visualizzando gli elementi QML usando la Graphic Scene. Altrimenti, possiamo esportare il nostro codice C++ in un plugin che potrà essere letto dal tool "qmlviewer&quot;:http://doc.qt.nokia.com/4.7/qmlviewer.html. Per la nostra applicazione implementiamo le funzioni di caricamento e salvataggio per poi esportarle come un plugin. In questo modo, dobbiamo solo caricare direttamente il file QML invece di eseguire un file eseguibile.

Esporre classi C++ in QML

Implementeremo il caricamento e salvataggio dei file attraverso Qt e C+. Le classi e le funzioni C+ possono essere usare in QML registrandole. Le classi hanno bisogno di essere compilate come plugin Qt e i file QML devo conoscere dove sono localizzati i plugin.

Per la nostra applicazione, dobbiamo creare i seguenti elementi:

  1. Una classe Directory che gestirà le operazioni legate alle directory
  2. Una classe File che sarà un "QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html, che simulerà la lista di files nella directory
  3. Una classe plugin che registrerà la classe per il contenuto QML
  4. Un progetto Qt che compilerà il plugin
  5. Un file qmldir che informerà il tool qmlviewerfile sulla locazione del plugin

Costruire il plugin Qt

Per costruire il plugin, abbiamo bisogno di specificarlo nel file di progetto Qt. Innanzitutto, i sorgenti,gli headers e i moduli devono essere aggiunti al nostro file di progetto. Tutti i file C++ e di progetto devono essere nella directory filedialog.

<br /> In cppPlugins.pro:

TEMPLATE = lib<br /> CONFIG ''= qt plugin<br /> QT''= declarative

DESTDIR ''= ../plugins<br /> OBJECTS_DIR = tmp<br /> MOC_DIR = tmp
<br /> TARGET = FileDialog
<br /> HEADERS''= directory.h  file.h  dialogPlugin.h

SOURCES += directory.cpp  file.cpp  dialogPlugin.cpp<br />

In particolare, compiliamo Qt con i moduli dichiarativi e settiamolo come plugin, avremo bisogno di un lib template. Metteremo poi il plugin compilato nella sua directory padre.

Registrare una classe in QML

<br /> In dialogPlugin.h:

#include &lt;QtDeclarative/QDeclarativeExtensionPlugin&amp;gt;

class DialogPlugin : public QDeclarativeExtensionPlugin<br /> {<br /> Q_OBJECT

public:<br /> void registerTypes(const char *uri);

};<br />

La nostra classe plugin, DialogPlugin è una sottoclasse di "QDeclarativeExtensionPlugin&quot;:http://doc.qt.nokia.com/4.7/qdeclarativeextensionplugin.html. Dobbiamo implementare la funzione ereditata, "registerTypes()":http://doc.qt.nokia.com/4.7/qdeclarativeextensionplugin.html#registerTypes. Il file dialogPlugin.cpp si prenta cosi:

<br /> DialogPlugin.cpp:

#include &quot;dialogPlugin.h&amp;quot;<br /> #include &quot;directory.h&amp;quot;<br /> #include &quot;file.h&amp;quot;<br /> #include &lt;QtDeclarative/qdeclarative.h&amp;gt;

void DialogPlugin::registerTypes(const char '''uri){
<br /> qmlRegisterType&amp;lt;Directory&amp;gt;(uri, 1, 0, &quot;Directory&amp;quot;);<br /> qmlRegisterType&amp;lt;File&amp;gt;(uri, 1, 0,&quot;File&amp;quot;);<br /> }
<br /> Q_EXPORT_PLUGIN2(FileDialog, DialogPlugin);<br />


La funzione "registerTypes()":http://doc.qt.nokia.com/4.7/qdeclarativeextensionplugin.html#registerTypes registra le nostre classi File e Directory in QML. Questa funzione necessità di un nome per la classe per il suo template, un numero di versione maggiore e minore e un nome per la nostre classi.
Dovremmo esportare il plugin usando la macro "Q_EXPORT_PLUGIN2&quot;:http://doc.qt.nokia.com/4.7/qtplugin.html#Q_EXPORT_PLUGIN2#q-export-plugin2. Notate nel nostro file dialogPlugin.h, abbiamo messo la macro "Q_OBJECT&quot;:http://doc.qt.nokia.com/4.7/qobject.html#Q_OBJECT macro all'inizo della classe. Dobbiamo quindi lanciare qmake sul progetto per generare i necessari codici meta-oggetto di Qt.
h4. Creare proprietà QML nella classi C++
Possiamo creare degli elementi e delle proprietà QML usando C++ e il sistema meta-oggetto di Qt. Possiamo implementare delle proprietà usando gli slot e signal, per farli conoscere a Qt. Queste proprieta possono poi essere usate in QML.
Per l'editor di testi, abbiamo bisogno di abilitare il caricamento e salvataggio dei files. Tipicamente, queste funzionalità sono contenute in un file dialog. Fortunatamente, possiamo usare "QDir&quot;:http://doc.qt.nokia.com/4.7/qdir.html, "QFile&quot;:http://doc.qt.nokia.com/4.7/qfile.html e "QTextStream&quot;:http://doc.qt.nokia.com/4.7/qtextstream.html per implementare la lettura delle cartelle e i flussi di input/output.


<br />class Directory : public QObject{
<br /> Q_OBJECT
<br /> Q_PROPERTY(int filesCount READ filesCount CONSTANT)<br /> Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged)<br /> Q_PROPERTY(QString fileContent READ fileContent WRITE setFileContent NOTIFY fileContentChanged)<br /> Q_PROPERTY(QDeclarativeListProperty&amp;lt;File&amp;gt; files READ files CONSTANT )
<br /> <br />


La classe Directory usa il sistema meta-oggetto di Qt per registrare le proprietà di cui ha bisogno per realizzare la gestione dei file. La classe Directory è esportata come plugin e usabile in QML come un elemento Directory. Ciascuna delle proprietà elencate che utilizza la macro "Q_PROPERTY&quot;:http://doc.qt.nokia.com/4.7/qobject.html#Q_PROPERTY è una proprietà QML.
Q_PROPERTY dichiara una proprietà, così come le sue funzioni di lettura e scrittura nel sistema meta-oggetto di Qt. Per esempio la proprietà filename, di tipo "QString&quot;:http://doc.qt.nokia.com/4.7/qstring.html, è leggibile usando la funzione filename() e scrivibile usando la funzione setFilename(). Inoltre. c'è un segnale associato alla proprietà filename chiamato filenameChanged(), che è emesso quando la proprietà cambia. Le funzioni di lettura e scrittura sono dichiarate pubbliche nel file header.
Allo stesso modo, abbiamo le altre proprietà dichiarate ai loro usi. La proprietà filesCount indica il numero di file in una directory. La proprietà filename è settata sul nome del file corrente selezionato e il caricamento/salvattaggio del contenuto del dile è memorizzato nella proprietà fileContent.


<br /> Q_PROPERTY(QDeclarativeListProperty&amp;lt;File&amp;gt; files READ files CONSTANT )<br />


La proprietà files list è una lista di tutti i file filtrati nella directory. La classe Directory è implementata per filtrare i file non validi; solo i file con estensione .txt sono validi. Inoltre, "QLists&quot;:http://doc.qt.nokia.com/4.7/qlist.html può essere utilizzata nei file QML dichiarandoli come "QDeclarativeListProperty&quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html in C+. L'oggetto template deve ereditare da un "QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html, quindi, la classe File deve anche ereditare da QObject. Nella classe Directory, l'elenco di oggetti File che è memorizzato in un Qlist chiamato m_fileList.

<br /> class File : public QObject{
<br /> Q_OBJECT<br /> Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
<br /> <br /> };<br />


Le proprietà possono quindi essere utilizzate in QML come parte del elemento della proprietà Directory. Notate che non abbiamo bisogno di creare un identificatore id nel nostro codice C.


<br /> Directory{<br /> id: directory
<br /> filesCount<br /> filename<br /> fileContent<br /> files
<br /> files[0].name<br /> }<br />


Siccome QML usa la sintassi e la struttura Javascript, possiamo scorrere l'elenco dei file e recuperare le sue proprietà. Per recuperare il nome del primo file, chiameremo files[0].name.
Le regolari funzioni C+ sono accessibili anche da QML. Il caricamento e salvataggio implementati in C++ sono dichiarati usando la macro "Q_INVOKABLE&quot;:http://doc.qt.nokia.com/4.7/qobject.html#Q_INVOKABLE. Altrimenti, possiamo dichiarare le funzioni cme slot e saranno accessibili da QML.


<br />In Directory.h:
<br /> Q_INVOKABLE void saveFile&amp;amp;#40;&amp;#41;;<br /> Q_INVOKABLE void loadFile&amp;amp;#40;&amp;#41;;<br />


La classe Directory deve inoltre notificare agli altri oggetti ogni volta che cambia il contenuto della directory. Questa funzione viene eseguita utilizzando un segnale. Come accennato in precedenza, i segnali QML devono avere un gestore corrispondente con prefisso i loro nomi. Il segnale è chiamato directoryChanged e viene emesso quando c'è un aggiornamento delal directory. L'aggiornamento semplicemente ricarica il contenuto della directory e aggiorna la lista dei files validi nella directory. Gli oggetti QML possono essere notificati collegando un azione al segnale onDirectoryChanged.
La lista di proprietà deve essere ulteriormente esplorata. Questo perché le proprietà list utilizzano delle chiamate per accedere e modificare il contenuto dell'elenco. La proprietà list è di tipo QDeclarativeListProperty&lt;File&gt;. Ogni volta che si accede alla lista, la funzione di accesso deve restituire un QDeclarativeListProperty&lt;File&gt;. Il template File, ha bisogno di derivare da un QObject. Inoltre, per creare "QDeclarativeListProperty&quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html, la lista di accesso e modifica devono essere passati al construttore come puntatori a funzione. La lista, in questo caso QList, deve anche essere una lista di puntatori a files.
Il costruttore "QDeclarativeListProperty&quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html e l'implementazione della Directory:


<br /> QDeclarativeListProperty ( QObject''' object, void * data, AppendFunction append, CountFunction count = 0, AtFunction at = 0, ClearFunction clear = 0 )<br /> QDeclarativeListProperty&amp;lt;File&amp;gt;( this, &amp;m_fileList, &amp;appendFiles, &amp;filesSize, &amp;fileAt, &amp;clearFilesPtr );<br />

Il costruttore passa dei puntatori alla funzione che li accoda alla lista, conta la lista, recupera l'oggetto usando un indice e svuota la lista. Solo la funzione di accodamento è obbligatoria. Si noti che il puntatore a funzione deve corrispondere alla definizione di "AppendFunction&quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html#AppendFunction-typedef, "CountFunction&quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html#CountFunction-typedef, "AtFunction&quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html#AtFunction-typedef, o "ClearFunction&quot;:http://doc.qt.nokia.com/4.7/qdeclarativelistproperty.html#ClearFunction-typedef.

<br /> void appendFiles(QDeclarativeListProperty&amp;lt;File&amp;gt; * property, File * file)<br /> File* fileAt(QDeclarativeListProperty&amp;lt;File&amp;gt; * property, int index)<br /> int filesSize(QDeclarativeListProperty&amp;lt;File&amp;gt; * property)<br /> void clearFilesPtr(QDeclarativeListProperty&amp;lt;File&amp;gt; *property)<br />

Per semplificare la nostra file dialog, la classe Directory filtra i files di testo non validi, che non hanno estensione .txt. Se un file non ha estensione .txt, non sarà visibile nella nostra file dialog. Inoltre, l'applicazione consente di verificare che i file salvati hanno estensione. Directory utilizza "QTextStream&quot;:http://doc.qt.nokia.com/4.7/qtextstream.html per leggere il file e per esportare il contenuto in un file.

Con il nostro elemento Directory, possiamo recuperare i file come lista, conoscere quanti file ci sono nella directory dell'applicazione, ottenere il nome del file e il suo contenuto come stringhe, e notificare se ci sono cambiamenti nel contenuto della directory.

Per compilare il plugin, lanciamo qmake sul file di progetto cppPlugins.pro, e lanciamo un make per compilare e trasferire il plugin nella directory dei plugins.

Integrare il File Dialog nel file Menu

Il nostro FileMenu deve visualizzare l'elemento FileDialog, contenente la lista di files in una directory, consentendo all'utente di selezionarne uno cliccando sulla lista. Abbiamo bisogno di assegnare i pulsanti del salvataggio e caricamento alle loro rispettive azioni. Il file FileMenu contiene un input di testo editabile per consentire all'utente di inserire il nome di un file attraverso la tastiera.

L'elemento Directory è usato nel file FileMenu.qml e notifica all'elemento FileDialog che la directory ha aggiornato il suo contenuto. Questa notifica è eseguita dal gestore del signal onDirectoryChanged.

<br /> In FileMenu.qml:

Directory{<br /> id:directory<br /> filename: textInput.text<br /> onDirectoryChanged: fileDialog.notifyRefresh()<br /> }<br />

Mantenendo con la semplicità della nostra applicazione, il filedialog sarà sempre visibile e non visualizzaremo file di testo non validi, che non hanno un estensione .txt.

<br />In FileDialog.qml:

signal notifyRefresh()<br /> onNotifyRefresh: dirView.model = directory.files<br />

L'elemento FileDialog visualizza il contenuto della directory leggendo le sue proprietà chiamate files. I files sono usati come modelli dell'elemento "GridView&quot;:http://doc.qt.nokia.com/4.7/qml-gridview.html, che visualizza gli oggetti in una griglia in accordo con il suo delegato. Il delegato gestisce l'aspetto del modello e il nostro file dialog semplicemente crea una griglia con un testo centrato nel mezzo. Cliccando sul nome del file si visualizzerà un rettangolo per evidenziare il nome del file. Il FileDialog è notificato ogni volta che il segnale notifyRefresh è emesso, ricaricando i files nella directory.

<br /> In FileMenu.qml:

Button{<br /> id: newButton<br /> label: &quot;New&amp;quot;<br /> onButtonClick:{<br /> textArea.textContent = &quot;&quot;<br /> }<br /> }<br /> Button{<br /> id: loadButton<br /> label: &quot;Load&amp;quot;<br /> onButtonClick:{<br /> directory.filename = textInput.text<br /> directory.loadFile&amp;amp;#40;&amp;#41;<br /> textArea.textContent = directory.fileContent<br /> }<br /> }<br /> Button{<br /> id: saveButton<br /> label: &quot;Save&amp;quot;<br /> onButtonClick:{<br /> directory.fileContent = textArea.textContent<br /> directory.filename = textInput.text<br /> directory.saveFile&amp;amp;#40;&amp;#41;<br /> }<br /> }<br /> Button{<br /> id: exitButton<br /> label: &quot;Exit&amp;quot;<br /> onButtonClick:{<br /> Qt.quit()<br /> }<br /> }<br />

Il nostro FileMenu può ora connette le sue rispettive azioni. Il saveButton trasferirà il testo dal TextEdit sulla proprietà fileContent della directory, poi copierà il nome dall' input textedit. Finalmente, il pulsante chiamerà la funzione saveFile&amp;#40;&#41;, salvando il file. Il pulsante loadButton ha una simile esecuzione. Inoltre, l'azione New svuoterà il contenuto del TextEdit.

Inoltre, i pulsanti EditMenu sono collegati alle funzioni di TextEdit per copiare, incollare e selezionare tutto il testo nell'editor di testo.

p=. editor di testo quasi completo

Completamento Editor di testi

p=. editor di testi finito

L'applicazione può funzionare come un semplice editor di testi, in grado di accettare il testo e salvarlo in un file. L'editor di testo può anche caricare un file e eseguire la manipolazione del testo.