joi, 14 mai 2020

Qt - Saptamana a 13-a Cap 12 + 13 in avans trimis

Buna ziua,

Bun venit la intalnirea cu Qt-ul din saptamana a XIII-a.

Ce ne propunem astazi:

1) Intai sa va trimit capitolul de azi al cartii.
Cei dintre dvs care nu au trimis portofoliul de lucrari de laborator, directoare arhivate,sunt rugati (elegant spus) sa isi faca lucrarile de laborator si sa le trimita pe e-mail la adresa cunoscuta.

2) Ne ocupam azi sa vedem utilizarea unei clase noi de obiecte Qt, cele care se ocupa cu timpul: QTimer si QTime.

3) Ce se mai poate face ... poate si meniuri ... vom vedea.

Va rog sa asteptati venirea capitolului .pdf pe e-mail.

Ok, ati primit e-mail-urile. Acum sa studiem impreuna Cap 12.
Ca de obicei voi comenta cele scrise...

Deschideti la pagina: [pg 159].
Ati gasit care sunt noutatile promise ale capitolului ?
Dar lucrurile deja stiute ?

Care sunt noutatile promise ale capitolului ?
R: Deocamdata ne propunem sa lucram in Qt 5, ceva care foloseste clasele QTimer si QTime. Paranteza din titlu sugera ca sunt doua clase diferite.

Dar lucrurile deja stiute ?
R: Organizarea de proiect, o gasiti la pagina urmatoare: [pg 160]
- avem de facut un program care foloseste o clasa al carui nume s-ar traduce prin "ceasdigital", digitalclock, si care se prezinta sub forma a doua fisiere:
- digitalclock.h
- digitalclock.cpp
Vom folosi aceasta clasa mai departe.

Dati pagina la [pg 160].
Cam asa va arata proiectul nostru in lucru, iar sus gasiti imaginea interfetei.


     In esenta e un afisaj pe mai multi digiti, 
in stil QLCDNumber vom vedea cati si cum facut.

Ne pregatim sa incepem proiectul, dati pagina la [pg 161]. Cititi-o !

Haideti sa incercam sa il facem din mers... printre comentarii... deschideti Qt Creator-ul !

Incepeti un nou proiect:


 Sa fie de tipul Empt Qmake Project, si dati-i un nume sugestiv:

Urmeaza Next,Next,Finish.
Si ne apucam de editat fisierul .pro.

Ceea ce aveti in manual este fisierul .pro in forma finala, deocamdata incepeti cu un fisier .pro de forma:

TEMPLATE = app
TARGET = QTDigitalClock
QT += core gui
QT += widgets
HEADERS +=
SOURCES +=

Intrebare de control:
Ce inseamna fiecare dintre randurile de mai sus ?

Intrebare de control:
La ce versiune de Qt nu este nevoie de toate ?

Intrebare de control:
La ce varianta a Qt-ului , pentru ce SO, am recomandat sa le folositi pe toate 1

Deocamdata ar trebui sa aveti un proiect care arata cam asa:


Si este momentul sa adaugam in proiect calsele de obiecte necesare:

Folositi fereastra aceasta !

Intrebare de control:
Daca nu v-am fi spus, cum se justifica alegerea celor doua optiuni marcate cu albastru ?

Acum dati pagina la pagin 162-163 si cititi declaratia de clasa de la pagina 163 de sus!

#include <QLCDNumber>

class DigitalClock : public QLCDNumber
{
    Q_OBJECT
public:
    DigitalClock(QWidget *parent = 0);
private slots:
    void showTime();
};


Intrebare de control:
Ce ne spune randul acesta ?

class DigitalClock : public QLCDNumber
Raspuns: Ne indica faptul ca am derivat, imposibil sa nu stiti notiunea, clasa noastra  DigitalClock in mod public din clasa QLCDNumber !

Acset lucru il puteti indica in fereastra urmatoare:


Apoi, Next, Next, Finish. OK ?

Ar trebui acum sa completati codul declaratiei clasei DigitalClock, dar atentie, scrieti-l fireste in digitalclock.h !  In prim plan va aparea digitalclock.cpp ! Dati click pe digitalclock.h in arborele proiectului !

Si ajungeti aici !

Completati declaratia clasei !

Aici observati o chestie draguta, cel putin la Qt 5.9 1 Cand adaugati : QWidget * parent = 0 apare un beculet minuscul dupa finalul randului, indicand o sugestie. Dati click pe el si vi se adauga in implementarea clasei, si parametrii declarati, deja in fisierul .h.



Reveniti la declaratia clasei, din manual  [pg 163] si observati ca mai avem ceva de adaugat ! Slotul privat !

Este prima oara cand intalnim un slot privat ! Asta inseamna ca va exista ceva inauntrul clasei care va trimite semnale ce vor fi receptionate pe acest slot !

Intrebare de control:
Ce semnale vin dinauntrul unui ceas ?
Indicatie: Daca aveti un ceas mecanic, puneti-l la ureche ! :))

Si la ce va folosi, foarte probabil slotul ? Ati inteles !
Pina la urma este chiar perfect normal:

#include <QLCDNumber>

class DigitalClock : public QLCDNumber
{
    Q_OBJECT
public:
    DigitalClock(QWidget *parent = 0);
private slots:
    void showTime();

 };

Intrebare de control:
Cum se numeste metoda, (aka functia inclusa in clasa, pentru cei care au uitat trermenul de metoda) care va fi apelata regulat, la fiecare semnal care vine pe slot ? Sare in ochi nu ?

#include <QLCDNumber>

class DigitalClock : public QLCDNumber
{
    Q_OBJECT
public:
    DigitalClock(QWidget *parent = 0);
private slots:
    void showTime();

 };

Nu uitati acest ";" final, lipsa lui poate duce la erori de compilare urate.

Acum ca ati adaugat slotul, imaginea ar fi asa:


Acum, cititi va rog explicatiile de la pg [163-164]. Va las cateva minute cu ele...
Urmeaza sa continuam cu implementarea clasei.

Acum dati la pagina 165 sa citim despre implementarea clasei.

Implementarea este formata din m

ai multe parti:
Chiar de la inceput includem tot ce e nevoie:

//----------------------- digitalclock.cpp------------------------------------//
#include <QtGui>
#include ”digitalclock.h”
//! [0]


Observati ca headerul este deja inclus, de cand am creat impreuna fiseirele .h si .cpp ale clasei.


 Se aduga acum constructorul clasei, acea metoda care, stiti voi, are numele clasei si se ocupa cu toate initializarile necesare obiectelor din acea clasa (recapitulez !!).

DigitalClock::DigitalClock(QWidget *parent)
: QLCDNumber(parent)
{
  setSegmentStyle(Filled);
  QTimer *timer = new QTimer(this);
  connect(timer, SIGNAL(timeout()), this, SLOT(showTime()));
  timer->start(1000);
  showTime();
  setWindowTitle(tr(”Digital Clock”));
  resize(150, 60);
}
//! [0]

Intrebari de control:
- De unde , din ce clasa, este luata si apelata metoda: setSegmentStyle(Filled);
- Nu cumva ar fi fost mai bine sa declaram variabila timer ca atribut in clasa de obiecte si nu ca variabila locala ? Avantaje si dezavantaje ale acestor abordari ?
- Era neaparat nevoie sa se apeleze direct showTime() ?
- Ce face setWindowTitle(tr(”Digital Clock”)); ? Evident, nu !
- Ce credeti ca face : timer->start(1000); ?
- Cum obtineti explicatii despre clasa QTimer ? Apasati F1 sau Fn+F1 ! Incercati !

Dati pagina: [pg 166] cititi explicatiile.

//! [1]
void DigitalClock::showTime()
//! [1] //! [2]
{
  QTime time = QTime::currentTime();
  QString text = time.toString(”hh:mm”);
  if ((time.second() % 2) == 0)
    text[2] =  ́ ́;;
  display(text);
}
//! [2]

Intrebari de control:
- De ce este scris: QTime::currentTime(); ?
- Carei claseii apartine metoda toString(”hh:mm”); ?
- Care simbol din ceea ce ar fi, generic ora: hh:mm este inlocuit cu spatiu, cand se intra pe ramura "then" a if-ului ?
- Din ce clasa provine metoda  display ?
 
Dati pagina la [pg 167].
Adaugati in proiect un fisier .cpp pe nume main .cpp !

Acesta este un C++ source file ! Numiti fisierul main.cpp, Next,Next,Finish.

Intrebare de control :
Prin ce difera aceasta adaugare de adaugarea unei clase ?

Cititi cu atentie explicatiile de la [pg 167] !!!

//------------------------ main.cpp----------------------------------------//
#include <QApplication>
#include <QLCDNumber> // pt QT 5.x Linux Ubuntu
#include ”digitalclock.h”
int main(int argc, char *argv[])
{
  QApplication app(argc, argv);
  DigitalClock clock;
  #if defined(Q_OS_SYMBIAN)
     clock.showMaximized();
  #else
     clock.show();
  #endif
  return app.exec();
}
//----------------------------------------------------------------------------//

Cateva indicatii de lucru:
- Atentie la ghilimelele stringurilor ! Puneti ghilimele de program, nu de acelea de Office, superioare si inferioare, ca in carte ! Corectati !
- Sa nu va sperie mesajele de eroare !
- Daca un rand cu o metoda sau o constanta apare scris cu negru, este foarte probabil sa fie nevoie sa includeti clasa respectiva, deoarece nu este inclusa !
- Adaugati in digitalclock.cpp headerele claselor folosite:
#include <QLCDNumber>
#include <QTimer>
- Corectati ghilimelele de la randul: #include ”digitalclock.h”

- Daca ceasul nu functineaza, si ramane blocat, cu mesajul
QObject::connect: No such slot QLCDNumber::showTime()
puteti suspecta:
-- o nepotrivire intre numele semnalului si al slotului.(Nu aici.)
--Este posibil ca mesajul sa apara din lipsa macroului Q_OBJECT in declaratia de clasa din fisierul .h! 
--Si nu uitati sa includeti clasa de baza, aici QLCDNumber, in fisierul .h.
Altfel de unde si-ar putea lua clasa din care va deriva clasa ceasurilor ?



- Pe sistemul meu, QT-ul ma invata ca pot folosi niste macrouri, pentru setarile de scalare, ceea ce este util cand dezvoltati aplicatiii mobile.
Warning: QT_DEVICE_PIXEL_RATIO is deprecated. Instead use:
QT_AUTO_SCREEN_SCALE_FACTOR to enable platform plugin controlled per-screen factors.
QT_SCREEN_SCALE_FACTORS to set per-screen factors.
QT_SCALE_FACTOR to set the application global scale factor.

Dupa pauza "intram in laborator" si depanam aplicatia ...

Ghinionisti cei care ... caz in care va trebui ceva reprogramat. Ruleaza pe Linux cu Qt 5.5.1.

O alta varianta de implementare. Sursele complete: Qt 5.9

//------------------------ main.cpp----------------------------------------//#include <QApplication>
#include <QLCDNumber> // pt QT 5.x Linux Ubuntu
#include <QTimer>     // Includeti si QTimer
#include "digitalclock.h"
int main(int argc, char *argv[])
{
  QApplication app(argc, argv);
  DigitalClock clock;

  QTimer *timer = new QTimer(&clock);
  DigitalClock::connect(timer, SIGNAL(timeout()), &clock, SLOT(showTime()));
  timer->start(1000);

  #if defined(Q_OS_SYMBIAN)
     clock.showMaximized();
  #else
     clock.show();
  #endif
  return app.exec();
}

//----------------------------------------------------------------------------//


Remarcati Timerul adus in programul principal si noua declaratie a conexiunii.

// -- digitalclock.h---//

#ifndef DIGITALCLOCK_H
#define DIGITALCLOCK_H
#include <QLCDNumber>

class DigitalClock : public QLCDNumber
{
    Q_OBJECT
public:
    DigitalClock(QWidget * parent = 0);
private slots:                           
    void showTime();
};

#endif // DIGITALCLOCK_H


//----------------------------------//

//----------------------- digitalclock.cpp------------------------------------//
#include <QtGui>
#include <QLCDNumber>
#include <QTimer>

#include "digitalclock.h"
//! [0]
DigitalClock::DigitalClock(QWidget *parent)
  : QLCDNumber(parent)
{
    setSegmentStyle(Filled);

    //QTimer *timer = new QTimer(this);
    //connect(timer, SIGNAL(timeout()), this, SLOT(showTime()));
    //timer->start(1000);


    showTime();
    setWindowTitle(tr("Digital Clock"));
    resize(150, 60);
}
//! [0]


//! [1]
void DigitalClock::showTime()
//! [1] //! [2]
{
  QTime time = QTime::currentTime();
  QString text = time.toString("hh:mm");
  if ((time.second() % 2) == 0)
    text[2] =  ' ';
  display(text);
}
//! [2]



//----------------------------------//

Remarcati Timerul scos din clasa ceasului.


Intrebare de control:
- Timerul poate fi scos din Ceas si pus in main. Este mai eleganta aceasta solutie ? De ce da, de ce nu ?

Exercitiu:Cum adaugati si un mic buton de [Quit] pe interfata ceasului ?

Pentru un listing complet al solutiei, aveti o postare mai noua: Qt - Saptamana a 13-a Laborator.


Sfarsit.

Niciun comentariu:

Trimiteți un comentariu