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]>