joi, 30 aprilie 2020

Qt - Saptamana a 11-a


Buna ziua si bun venit

la intalnirea cu cel mai Qt software.

Planul de astazi:

1) Voi trimte pe e-mail-ul celor care s-au inscris (unii dintre colegii dvs cred ca nu au facut-o, caz in care ii rog s ceara capitolul de carte de la colegi) capitolul al 10-lea al manualului "Introducere in C++ extins folosind Qt Creator". [pg 137-148]

Ati primit deja paginile din carte ale acestui capitol.

2)Am sa va rog sa revedeti capitolul despre Automate din cursul LFA.  Paginile [47-71] din cursul de LFA si comentariile lui de pe acest blog.


Va trimit acum si capitolul din teoria automatelor, din cursul de LFA.
OK. L-ati primit deja.

3) La partea practica vom implementa exemplul despre automate discutat mai inainte (astept ca de obicei codurile arhivate pe e-mail).


Sa parcurgem impreuna paginile, sa incepem cu pg 137.
Pagina va spune in esenta ce va contine capitolul, niste clase Qt care folosesc la implementarea notiunilor de teoria automatelor finite deterministe. Si aminteste cateva utilizari posibile ale automatelor.

Sa mergem la pagina 138. Aici pe scurt e vorba despre ...

1) Implementari ale automatelor in limbaje cu GOTO-uri. Sau in assembler, limbaj care are instructiunea jump/jmp.
In aceste limbaje definiti niste puncte din program marcate cu etichete si
atunci cand este momentul, dupa citirea unui caracter de la intrarea automatului (sau primirea unui semnal de alt fel) se sare la eticheta corespunzatoare starii.
Acolo poate fi o portiune de cod care executa ceea ce are de executat, atunci cand automatul ajunge in acea stare. Si iar se citeste un simbol de la intrare si
ciclul se repeta.

Mecanismul seamana putin cu mecanismul intreruperilor hardware.
Intrebare de control: Este acelasi lucru sau sunt deosebiri intre mecanismul intreruperilor hardware si un automat ?
(A) - Sunt practic la fel ?
(B) - Exista o deosebire ?
(C) - Unul e mai general decat celalalt ? Care ?

2) O alta implementare posibila a automatelor se facea in limbajele structurate si avea la baza:

O bucla ...
...                     /|\
...                      |
...                      |
care se repeta  |

pina cand automatul ajungea iun starea finala. O variabila tinea loc de stare, memora numarul starii.

La inceput, inainte de intrarea in bucla, variabila primea ca valoare numarul starii initiale.
Apoi, in bucla, se citea un simbol de la intrare, si se trecea printr-o succesiune de if-uri care testau:
- daca era o anumita stare curenta si un anumit simbol la intrare caz in care variabila stare isi schimba valoarea(, si bucla se relua.).

Exercitiu:
Schitati in limbajul favorit o astfel de implementare a unui automat.

3) O alta implementare se putea face memorand tabela functiei delta, chiar intr-o tabela (limbajele permit notiunea de vector/matrice).
O bucla merge pina cand ajungem la o stare finala,
in bucla daca este posibil, vechea stare se inlocuieste cu cea obtinuta din tabela functiei delta.
stare = delta (stare, simbol).

Bineinteles, daca ea nu e definita, automatul se blocheaza, se opreste.

Nota: Odata cu trecerea intr-o alta stare, automatul poate sa si execute ceva ce are de executat, ceva coresp acelei stari.

Acest gen de implementari ale automatelor sunt cumva limitate la un singur automat, ceea ce e limitativ. Varianta (3) cu bucla si cu tabela ar putea implementa simultan, sincronizat, schimbarea starilor de la mai multe automate.

Dar implementari mai bune au aparut odata cu POO-ul, programarea orientata pe obiecte. Un mediu de programare modern va poate oferi obiecte pentru a implementa automate care isi schimba starea conform unor semnale venite dinafara si executa ceva cand ajung in aceste stari. Este si cazul Qt-ului.

Dati pagina la pagina:  139.

STL - standard template library nu contine automate, nu are un astfel de sablon. Dar Qt are niste obiecte speciale.

Exercitiu:
Rulati, deocamdata, exemplul States, din colectia de exemple Qt.
Il puteti gasi fie in sectiunea de exemple, fie cautand in index All-examples- si acolo pe lista, exemplul States. Fie cautand in Help States Example.

Veti gasi acolo o aplicatie in care starea unui sistem de widget-uri se schimba la o apasare pe un buton. Cititi codul ei abia la sfarsitul acestei lectii !!

Exercitiu:
Rulati exemplul Stickman. Acolo veti gasi un concept si mai interesant. Higraph-uri.

Dar inainte de a studia codurile acestor exemple (v-am aratat pozele doar ca sa le gasiti mai usor) sa parcurgem lectia despre automate in Qt:

Revedeti intai notiunile de teoria automatelor: pg 139-pg 140.
Acum putem sa implementam in Qt unul din cele mai simple automate.
Rolul exemplului este sa va familiarizeze cu nostiunile fundamentale pe care le veti gasi in exemplele din Help.

Unul din cele mai simple automate ar fi cel asociat butonului ON/OFF cu doua pozitii. Este clar ca avem de-a face cu un automat cu doua stari:

(ON) --------------------> (OFF)
         <--------------------

si cu doua tranzitii, una de la starea ON la OFF si alta invers, AMBELE declansate de acelasi (NUUU simbol) ci  eveniment: apasarea pe buton.

Ca actiuni de executat vom pune actiuni minimale:
- sa se scrie pe buton ON cand ajunge in starea ON
- sa se scrie pe buton OFF cand ajunge in starea OFF

                                                         |          /|\
                                                         |           |
                                     Apasa          |           |   Apasa
                                                        \|/          |


Dupa aceea facem:

Implementarea

Lucrati impreuna cu mine pe baza surselor din carte !

 Incepem un Empty Qt Project, (dar vom scrie noi fisierul .pro).
Dati nume proiectului.
Alegeti kit-ul cu care lucrati. Daca aceasta fereastra nu va apare sau nu aveti kit-ul definit, parcurgeti repede reinstalarea din saptamana a 5-a (sau a 6-a).
Sariti peste aceasta etapa, nu folosim instrumente de Project Management.
Si dati Finish.
Completati fisierul .pro:
 Acum creati un fisier sursa main.cpp:
Si adaugati codul sursa, pe care va rog sa il scrieti de mana si sa il studiati... il vom comenta impreuna in limita timpului:
Asa arata programul principal: main.cpp din proiectul nostru.
Corectati eventualele erori, de ex ghilimele cu probleme samd...daca aveti.
Iar cand rulati programul:
Apasand pe buton observati ca se schimba On cu Off.
 Click !
 Click !

Sa explicam cum se face aceasta, dar inaite de aceasta va rog cititi cu atentie sursa, ea are marcate pozitii care vor corespunde explicatiilor:

Implementarea este comentata pe sectiuni in manual. pg 145-148. Studiati-le va rog ! Pentru detalii despre clasele:
QState
QStateMachine
consultati Help-ul tinand mouse-ul pe numele clasei si apasand F1 sau Fn+F1.

Tema: Rezolvati exercitiile de la finalul capitolului.

Pentru cei care nu au manualul:

Implementarea comentată pe secțiuni:

Dacă nu ați identificat dintr-o privire elementele amintite (QSta-
teMachine, QState, addTransition() etc) în textul de mai sus, a venit
momentul să le discutăm unul câte unul:
La început sunt incluse în proiect bibliotecile necesare (la Qt 4.x am
avut nevoie să includem doar <QtGui> care pe atunci includea toate
elementele necesare. La Qt 5.x bibliotecile au fost separate pe module
și a fost nevoie să includem și clasele <QApplication> și <QPushBut-
ton>.

#include <QtGui>
#include <QApplication>
#include <QpushButton>

Funcția main() începe ca de obicei și primul lucru făcut este să de-
clare existența a trei variabile din tipurile (care sunt clase de obiecte)
QApplication, QPushButton, QStateMachine. Stările mașinii se defi-
nesc în secțiunea următoare:

//! [0]
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QPushButton button;
QStateMachine machine;
//! [0]

Automatul are două stări, corespunzătoare pozițiilor pornit („On”)
și oprit („Off ”) ale butonului. Sunt create dinamic două obiecte din
clasa QState. Nu sunt necesari alți parametri la crearea lor, construc-
torul clasei QState este apelat fără parametri, paranteza sa este goală.
Fiecărui obiect i se atribuie un nume folosindu-se metoda setObject-
Name (...).
Și, mai important, fiecare obiect QState este programat ca atunci
când se ajunge în acea stare, să facă un fel de „atribuire” modificând va-
loarea unui atribut al altui obiect. O asemenea „atribuire” va fi execu-
tată interpretativ, din mers, de metoda assignProperty (...), la intrarea
în acea stare (!).
Aceasta are trei parametri: adresa obiectului în care
se face modificarea, numele atributului modificat – aici este atributul
„text” - și valoarea nouă stabilită pentru acestui atribut.
Observați că atunci când se ajunge în starea off pe buton va fi scris
textul „Off ” și când se ajunge în starea on pe buton va fi scris textul
„On”.

//! [1]
QState *off = new QState();
off->assignProperty(&button, ”text”, ”Off ”);
off->setObjectName(”off ”);
QState *on = new QState();
on->setObjectName(”on”);
on->assignProperty(&button, ”text”, ”On”);
//! [1]

În secțiunea [2] se definesc tranzițiile, acelea care s-ar fi desenat ca
niște săgeți în graful automatului. Primul apel al metodei addTran-
sition(...) spune: Atunci când obiectul buton va lansa semnalul clic-
ked(...), mașina va trece din starea off în starea on. Off este primul cu-
vânt pe rând, on este ultimul, și este pus în paranteza cu argumente.
Așa le țineți mine. Tranziția este atașată obiectului care este starea sa
de pornire („pana” nu vârful săgeții). Mai trebuiesc precizate, la apelul
metodei care definește tranziția: obiectul ce ne dă semnalul, semnalul
și starea destinație a tranziției.

//! [2]
off->addTransition(&button, SIGNAL(clicked()), on);
on->addTransition(&button, SIGNAL(clicked()), off);
//! [2]

Acum spunem mașinii că ei, nu alteia, îi aparțin cele două stări. Este
ca și cum l-am construi pe Q – mulțimea stărilor prin reuniuni succe-
sive cu câte o stare. Practic în secțiunea trei adăugăm cele două stări
on și off – obiecte de clasa QState – la mulțimea stărilor mașinii. Se
folosește în acest scop metoda addState(...) a obiectului de clasă QSta-
teMachine.

//! [3]
machine.addState(off);
machine.addState(on);
//! [3]

După cum spuneam și în introducere, mașina are o stare inițială care
trebuie marcată, declarată, altfel n-ar ști din ce stare să pornească. Și
bineînțeles, programul trebuie să pornească explicit mașina cu stări.
Dacă sunt mai multe mașini conteză care mașină pornește.

//! [4]
machine.setInitialState(off);
machine.start();
//! [4]

În secțiunea [5] a programului se apelează metode ale obiectului bu-
ton pentru a-l redimensiona, a-l afișa și a porni întregul mecanism de
procesare a evenimentelor.

//! [5]
button.resize(100, 50);
button.show();
return app.exec();
}
//! [5]

Și cu asta, gata. Puteți rula programul și vedea cum fiecare apăsare
pe buton duce la schimbarea textului de pe acesta, mărturie a schimbă-
rii stării mașinii cu stări.

Lectura suplimentara: 
Documentatia exemplelor States si Stickman.

Sfarsit.

Niciun comentariu:

Trimiteți un comentariu