TP Qt : code-barre
Transcription
TP Qt : code-barre
TP Qt : Code-barre © 2012 tv <[email protected]> - v.1.0 - le 11 juin 2012 Sommaire Manipulations 2 Objectifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Mise en situation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Travail demandé 2 Itération 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Itération 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Le code 39 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Le dessin 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Mise en oeuvre du code-barre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Il est fortement conseillé d’utiliser la documentation Qt de référence en français (http://qt.developpez.com/doc/) ou en anglais (http://qt-project.org/doc/). 1 TRAVAIL DEMANDÉ Manipulations Objectifs Les objectifs de ce tp sont : • utilisation de quelques widgets • mise en oeuvre du dessin et de l’impression dans Qt Mise en situation Dans ce tp, on vous propose de développer une application graphique en Qt en utilisant des widgets permettant de générer et imprimer des code-barres (fr.wikipedia.org/wiki/Code_barre) Code39 (fr.wikipedia.org/wiki/Code_39). On va développer l’application en deux itérations. Remarque : un développement itératif s’organise en une série de développement très courts de durée fixe nommée itérations. Le résultat de chaque itération est un système partiel exécutable, testé et intégré (mais incomplet). Travail demandé Itération 1 Dans cette première itération, on s’attachera à créer sa propre boîte de dialogue en créant une nouvelle classe MyDialog qui héritera de la classe QDialog. Une instance de cette classe représentera la fenêtre de l’application : #include <QApplication> #include "mydialog.h" TP Qt : Code-barre 2 / 12 © 2012 tv <[email protected]> TRAVAIL DEMANDÉ int main( int argc, char **argv ) { QApplication a( argc, argv ); MyDialog w; w.show(); return a.exec(); } Code 1 – main.cpp Et on obtiendra alors l’affichage suivant : Le fonctionnement de l’application est assez simple : • le bouton Générer assure le dessin du code-barre à l’écran et valide la possibilité de l’imprimer • le bouton Imprimer assure l’impression du code-barre vers l’imprimante choisie • le bouton Quitter permet de terminer l’application TP Qt : Code-barre 3 / 12 © 2012 tv <[email protected]> TRAVAIL DEMANDÉ La classe MyDialog devra intégrer les différents éléments graphiques suivants : Vous devez définir un positionnement de ces widgets avec des layouts afin de respecter l’affichage fourni dans la capture d’écran ci-dessus. L’instanciation des widgets et leur positionnement se fera dans le constructeur de la classe MyDialog (voir Code 4). Pour gérer les évenements et les actions entre l’utilisateur et l’application ou entre les widgets de l’application, Qt utlise un mécanisme d’évènements (signaux) et de récepteurs (slots). Chaque objet du programme (qui hérite de QObject et qui contient l’appel à la macro Q_OBJECT dans sa déclaration) peut émettre des signaux et proposer des slots de réception. Il suffit ensuite de connecter les signaux aux slots pour obtenir le déclenchement d’une action en présence d’un évènement. Ce mécanisme puissant permet aux différents objets de l’application de communiquer entre-eux de façon simple sans avoir à maintenir en permanence des références entre eux. TP Qt : Code-barre 4 / 12 © 2012 tv <[email protected]> TRAVAIL DEMANDÉ Dans notre situation, il faudra assurer au minimum la gestion des évèments et le déclenchement des actions représentées dans la capture d’écran ci-dessus. Le code-barre saisi dans un QLineEdit et le texte associé au QLabel sont de type QString. Question 1. Assurer la fabrication de l’application. Afin de simplifier la fabrication, Qt offre l’utilitaire qmake qui permet de générer un fichier Makefile à partir d’un fichier projet (extension pro). Un fichier projet décrit les fichiers qui composent le programme (fichiers sources, headers, ...) et certaines options de construction (bibliothèques, ...). Pour ce tp, le fichier .pro généré par qmake sera le suivant : ###################################################################### # Automatically generated by qmake (2.01a) dim. fvr. 5 16:14:41 2012 ###################################################################### TEMPLATE = app TARGET = codebarre DEPENDPATH += . INCLUDEPATH += . # Input HEADERS += mydialog.h generateurcodebarre.h SOURCES += main.cpp mydialog.cpp generateurcodebarre.cpp Code 2 – codebarre.pro Les différentes étapes pour fabriquer l’application demandée (sous GNU/Linux) sont : Étape 1. Créer un répertoire codebarre. Étape 2. Copier les fichiers fournis (main.cpp, mydialog.h et mydialog.cpp) dans le répertoire codebarre. Étape 3. Compléter les fichiers fournis (mydialog.h et mydialog.cpp) : travail effectué aux questions 2 et 3. Étape 4. Générer le fichier de projet codebarre.pro en utilisant qmake dans le répertoire contenant les sources à compiler. $ qmake -project Étape 5. Générer le fichier Makefile en utilisant qmake dans le répertoire contenant les sources à compiler. $ qmake Étape 6. Fabiquer l’application en utilisant make ou mingw32-make sous Windows. $ make TP Qt : Code-barre 5 / 12 © 2012 tv <[email protected]> TRAVAIL DEMANDÉ Étape 7. Tester l’application fabriquée. $ ./cesar Question 2. Compléter la déclaration de la classe MyDialog. #ifndef MYDIALOG_H #define MYDIALOG_H #include <QtGui> class GenerateurCodeBarre; class MyDialog : public QDialog { Q_OBJECT public: MyDialog( QWidget *parent = 0 ); private: QLineEdit *codebarre; QLabel *valeur; QPushButton *bGenerer; QPushButton *bImprimer; QPushButton *bQuitter; GenerateurCodeBarre *generateurCodeBarre; QIntValidator *intValidator; private slots: void generer(); void imprimer(); }; #endif Code 3 – mydialog.h Question 3. Compléter la définition de la classe MyDialog. #include <QtGui> #include "mydialog.h" #include "generateurcodebarre.h" MyDialog::MyDialog( QWidget *parent ) : QDialog( parent ) { valeur = new QLabel(this); TP Qt : Code-barre 6 / 12 © 2012 tv <[email protected]> TRAVAIL DEMANDÉ valeur->setText("Code barre :"); // TODO setWindowTitle(tr("TP codebarre")); setFixedHeight(sizeHint().height()); } void MyDialog::generer() { // TODO } void MyDialog::imprimer() { // TODO } Code 4 – mydialog.cpp Question 4. Fabriquer l’application et tester. Itération 2 Une fois l’itération 1 validée, on passe à la seconde itération qui a pour but de finaliser l’application. Remarque : dans un processus de développement itératif et incrémental, chaque développement s’ajoute et enrichit l’existant. Normalement, la nouvelle itération écrase la précédente et son numéro de version est incrémenté. Il est conseillé de conserver une copie fonctionnelle de l’itération 1. Dans certains cas, c’est une position de repli intéressante. Le code 39 Le code 39 est un code alphanumérique permettant de coder dans sa version d’origine 43 caractères, c’est-à-dire les chiffres de 0 à 9, les lettres de A à Z, 6 symboles y compris l’espace, plus un caractère particulier de début et fin de message (*). Un caractère particulier est utilisé pour marquer le début et la fin du symbole. Ce caractère est habituellement interprété par un astérisque (*), et n’est pas transmis lors de la lecture. Un symbole en code 39 se compose donc de : – Un espace blanc – Le caractère de début de message – Les caractères du message proprement dit – Le caractère de fin de message – Un espace blanc TP Qt : Code-barre 7 / 12 © 2012 tv <[email protected]> TRAVAIL DEMANDÉ Remarques : Il faut noter que les espaces blancs précédant le symbole lui-même sont indispensables pour la lecture. Le cas échéant, si l’utilisateur le souhaite, une clé de contrôle peut être ajoutée au message. Chaque caractère est composé de 9 éléments : 5 barres (noir) et 4 espaces (blanc). Chaque barre ou espace est large (représentant un bit à 1) ou étroit (représentant un bit à 0). Le codage de chaque caractère est donc la succession de 9 bits dont exactement 3 sont à 1 (barre large). Par exemple, voici les codes pour les valeurs de 0 à 9 : – 0→ − 000110100 (0x034) – 1→ − 100100001 (0x121) – 2→ − 001100001 – 3→ − 101100000 – 4→ − 000110001 – 5→ − 100110000 – 6→ − 001110000 – 7→ − 000100101 – 8→ − 100100100 – 9→ − 001100100 (0x064) L’ensemble des codes pourrait donc être déclaré de la manière suivante : int tableSymboles[44]= { 0x034, 0x121, 0x061, 0x025, 0x124, 0x064, 0x118, 0x058, 0x00d, 0x043, 0x142, 0x013, 0x046, 0x016, 0x181, 0x0d0, 0x085, 0x184, 0x08a, 0x02a }; 0x160, 0x109, 0x10c, 0x112, 0x0c1, 0x0c4, 0x031, 0x049, 0x04c, 0x052, 0x1c0, 0x094, 0x130, 0x148, 0x01c, 0x007, 0x091, 0x0a8, 0x070, 0x019, 0x103, 0x106, 0x190, 0x0a2, Exemple : 5→ − 100110000 → − donnera la séquence suivante : barre (noir) large - espace (blanc) étroit - barre étroite - espace large - barre large - espace étroit - barre étroite - espace étroit - barre étroite Les 9 bits du code binaire se lisent de la gauche vers la droite : – Les bits pairs correspondent aux barres noires et les impairs aux barres blanches – Un bit égal à 1 correspond à une barre épaisse et si 0 ce sera une barre fine TP Qt : Code-barre 8 / 12 © 2012 tv <[email protected]> TRAVAIL DEMANDÉ Le dessin 2D Il y a deux approches pour dessiner en 2D dans Qt : – un modèle fonctionnel basé sur QPainter – un modèle objet basé sur le framework Graphics View La classe QPainter est la classe de base de dessin bas niveau sur les widgets et les autres dispositifs de dessins : – QPainter fournit des fonctions hautement optimisées : il peut tout dessiner des lignes simples à des formes complexes. – QPainter peut fonctionner sur n’importe quel objet qui hérite de la classe QPaintDevice. Remarque : L’utilisation courante de QPainter est à l’intérieur de la méthode paintEvent() d’un widget : construire, personnaliser (par exemple le pinceau), dessiner et détruire l’objet QPainter après le dessin. Un widget est "repeint" : – Lorsque une fenêtre passe au dessus – Lorsque l’on déplace le composant – ... – Lorsque l’on le lui demande explicitement : repaint() entraîne un rafraichissement immédiat ou update() met une demande de rafraîchissement en file d’attente Important : Dans tous les cas, c’est la méthode paintEvent qui est appelée : void paintEvent(QPaintEvent* e) ; Pour dessiner dans un widget, il faut donc redéfinir QWidget : :paintEvent(). La classe QPainter fournit de nombreuses méthodes : – setPen() : lignes et contours (cf. QPen) – setBrush() : remplissage (cf. QBrush) – setFont() : texte (cf. QFont) – Lignes et contours : drawRect(), drawPoint(), drawLine(), ... – Remplissage : fillRect(), ... – Divers : drawText(), drawPixmap(), drawImage(), drawPicture() Exemple simple pour dessiner : class MyWidget : public QWidget { public: MyWidget( QWidget *parent = 0 ) : QWidget( parent ) {} void paintEvent(QPaintEvent* e) { QWidget::paintEvent(e); // effectue le comportement standard QPainter painter(this); // construire TP Qt : Code-barre 9 / 12 © 2012 tv <[email protected]> TRAVAIL DEMANDÉ QPen pen(QColor(Qt::black), 1); // personnaliser QBrush brush(QColor(Qt::black)); QRect barreFine = QRect(0, 0, 4, 100); // position x et y (en pixels) QRect barreEpaisse = QRect(0, 0, 8, 100); painter.setBrush(brush); painter.setPen(pen); painter.drawRect(barreFine); // dessiner une barre (fine) } // detruire }; Pour imprimer, il suffit de "dessiner" sur un objet de type QPrinter : class MyWidget : public QWidget { public: MyWidget( QWidget *parent = 0 ) : QWidget( parent ) {} void paintEvent(QPaintEvent* e) { QWidget::paintEvent(e); // effectue le comportement standard QPrinter printer; QPainter painter(&printer); // construire QString texte = "5"; QPen pen(QColor(Qt::black), 1); // personnaliser QBrush brush(QColor(Qt::black)); QFont font("Verdana", 12); QRect barreFine = QRect(0, 0, 4, 100); // position x et y (en pixels) QRect barreEpaisse = QRect(0, 0, 8, 100); QRect Texte = QRect(0, 105, 100, 60); painter.setBrush(brush); painter.setPen(pen); painter.setFont(font); painter.drawRect(barreFine); // dessiner une barre (fine) // ... painter.drawText(Texte, Qt::AlignCenter, "*" + texte + "*"); } // detruire }; TP Qt : Code-barre 10 / 12 © 2012 tv <[email protected]> TRAVAIL DEMANDÉ Qt fournit une boîte de dialogue QPrintDialog prête à l’emploi pour choisir l’imprimante et valider l’impression. Sa mise en oeuvre est assez simple à réaliser : QPrinter printer; QPrintDialog *dialog = new QPrintDialog(&printer, this); dialog->setWindowTitle(tr("Imprimer")); if (dialog->exec() == QDialog::Accepted) { //qDebug() << "c’est parti !"; // ... } Mise en oeuvre du code-barre Il vous faut maintenant créer une classe GenerateurCodeBarre qui prend en charge le dessin du code-barre et son impression. #ifndef GenerateurCodeBarre_H #define GenerateurCodeBarre_H #include <QtGui> class GenerateurCodeBarre : public QWidget { public: GenerateurCodeBarre(QWidget *parent = 0); ~GenerateurCodeBarre(); void paintEvent(QPaintEvent* e); void imprimer(QString codebarre); void dessiner(QString codebarre); private: //... }; #endif // GenerateurCodeBarre_H Code 9 – generateurcodebarre.h Question 5. Coder la classe GenerateurCodeBarre. Question 6. Coder les méthodes generer() et imprimer() de la classe MyDialog. TP Qt : Code-barre 11 / 12 © 2012 tv <[email protected]> TRAVAIL DEMANDÉ TP Qt : Code-barre 12 / 12 © 2012 tv <[email protected]>