Programmation d interfaces avec



Documents pareils
Construction d Interfaces Graphiques

AUVRAY Clément (168187) HOMBERGER Alexandre (186897) GLADE. Langages, outils et méthodes pour la programmation avancée Page 1 sur 12

IHM2. Eric Lecolinet - Télécom ParisTech 1. Toolkit graphique Qt Dessin interactif. Machines à états.

Warren PAULUS Robin GODEFROID. C++ - Interface Graphique avec Visual Studio 2010

Modéliser ses fenêtres avec Qt Designer

Guide de l utilisateur. Faites connaissance avec la nouvelle plateforme interactive de

Programmation système en C/C++

Édu-groupe - Version 4.3

Anne Tasso. Java. Le livre de. premier langage. 10 e édition. Avec 109 exercices corrigés. Groupe Eyrolles, , ISBN :

Démarrer et quitter... 13

Tutorial Terminal Server sous

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Table des matières ENVIRONNEMENT

Manuel de System Monitor

0.1 Mail & News : Thunderbird

Utilisation du client de messagerie Thunderbird

Java 7 Les fondamentaux du langage Java

TP1 : Initiation à l algorithmique (1 séance)

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

WINDOWS 8. Windows 8 se distingue par la présence de 2 interfaces complémentaires :

Logiciel de gestion pour restaurants et Bars

Installation et paramétrage de Fedora dans VirtualBox.

Installation et prise en main d UBUNTU

USTL - Licence ST-A 1ère année Initiation à la programmation TP 1

Interfaces graphiques avec l API Swing

Introduction à la programmation Travaux pratiques: séance d introduction INFO0201-1

Modéliser ses fenêtres avec Qt Designer

Mini_guide_Isis_v6.doc le 10/02/2005 Page 1/15

Organiser le disque dur Dossiers Fichiers

TIC. Tout d abord. Objectifs. L information et l ordinateur. TC IUT Montpellier

Indiquer l'espace libre sur le disque dur

SolidWorks edrawings et publications

Premiers pas avec VMware Fusion. VMware Fusion pour Mac OS X

Malgré son aspect spartiate, Freeplane offre de nombreuses fonctionnalités en particulier dans le domaine de la diffusion des cartes sur le Web.

Once the installation is complete, you can delete the temporary Zip files..

Découvrir l'ordinateur (niveau 2)

Fonctionnement de Windows XP Mode avec Windows Virtual PC

INTERWRITE Workspace

Cours. Cours 8 : Révisions. Importance. Interface homme-machine

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

Dans l idéal, ceci devrait être fait en amont pour chaque image envoyée sur l espace de stockage de votre site internet.

Cahier n o 6. Mon ordinateur. Fichiers et dossiers Sauvegarde et classement

Sélection du contrôleur

Utilisation de l éditeur.

Support de formation Notebook

Contenu Windows 8 MODULE 1 AVANT-PROPOS MODULE 2 INTRODUCTION À WINDOWS 8 MODULE 4 APPLICATIONS WINDOWS 8 PARTIE 1 MODULE 3 PARAMÈTRES DE WINDOWS 8

Introduction au langage C

MEMENTO D'UTILISATION Du T.N.I. SmartBoard (Version )

as Architecture des Systèmes d Information

Guide d utilisation. Version 1.1

ndv access point : Utilisation

Tutoriel code::blocks

MANUEL TBI - INTERWRITE

l'ordinateur les bases

Comment sélectionner des sommets, des arêtes et des faces avec Blender?

Contenu Microsoft Windows 8.1

L informatique en BCPST

Le logiciel de création de site internet IZISPOT est un outil très puissant et qui est assez simple après quelques temps d utilisation.

Manuel d utilisation NETexcom

Optimiser pour les appareils mobiles

Introduction à Windows 8

Initiation à linfographie

GUIDE D UTILISATION DU LOGICIEL DE TELE-MAINTENANCE. TEAM VIEWER Version 7.

GUIDE DE DÉMARRAGE. SitagriPro Infinite FINANCEAGRI. Un service. c o r p o r a t e

Programmer en JAVA. par Tama

Avant-propos FICHES PRATIQUES EXERCICES DE PRISE EN MAIN CAS PRATIQUES

MÉDICLICK! STUDIO 3 GESTION DES IMAGES ET PIÈCES JOINTES SOMMAIRE

Développement mobile MIDP 2.0 Mobile 3D Graphics API (M3G) JSR 184. Frédéric BERTIN

Développement d un logiciel de messagerie instantanée avec Dotnet (version simplifiée)

INTRODUCTION AU CMS MODX

Le langage C. Séance n 4

Programmation C. Apprendre à développer des programmes simples dans le langage C

Le cas «BOURSE» annexe

Notes pour l utilisation d Expression Web

Qu est-ce qu un Ordinateur

Mise en scène d un modèle dans l espace 3D

Chapitre 22 Optimisation pour diffusion à l'écran, pour le web

Dans l Unité 3, nous avons parlé de la

LANGAGUE JAVA. Public Développeurs souhaitant étendre leur panel de langages de programmation


Arborescence et création de dossiers

TP1 : Initiation à Java et Eclipse

Cours LG : Administration de réseaux et sécurité informatique. Dans les Paramètres Système onglet Processeur, le bouton "Activer PAE/NX"

Introduction à C++ et à wxwidgets

L espace de travail de Photoshop

iil est désormais courant de trouver sur Internet un document

Créer et partager des fichiers

Guide de l utilisateur Mikogo Version Windows

I Récupération de l'identifiant

Le cas «BOURSE» annexe

AIDE à l utilisation du cédérom «L athlétisme à l école» Niveau Primaire SOMMAIRE

Studio. HERITIER Emmanuelle PERSYN Elodie. SCHMUTZ Amandine SCHWEITZER Guillaume

Les pannes non bloquantes ou aléatoires :

Quelques outils pour le logiciel «Tux Paint»

Guide Utilisateur ArkadinAnywhere

Modifier les propriétés d'un widget

pcon.planner 6 Préparer et présenter une implantation en toute simplicité

MAILING KOMPOZER... 2 CREEZ UNE PAGE... 2 FORMAT DE LA PAGE... 2 AJOUTER DU TEXTE SUR UNE PAGE... 4

KompoZer. Composition du site : _ une page d'accueil : index.html. _ une page pour la théorie : theorie.html. _ une page pour les photos : photos.

Transcription:

Programmation d interfaces avec * Qt (Code less. Create more. Deploy everywhere) * de Qt Development Frameworks (anciennement Trolltech) (http://qt.digia.com) 1

Plan 4.Dessiner 5.Menu 0.Généralité 1. Widget 2.Signal et slot Utilisation Définition 6. Placement 7. Quelques classes 3.Evénements Barre de menus Menu surgissant Méthodes prédéfinies Filtres d événements Send & Post 2

0. Généralité GNOME Propose des toolkits GUI pour les environnements : GTK GDK KDE Qt CDE Motif Xt Xlib Protocole X Window System Bibliothèque en C++ : plus de 500 classes, apport positif du langage Objet. Portabilité, multi plates-formes : Unix, Linux, FreeBSD, Solaris, Windows, Mac, Excellente documentation html (classes, tutorials, exemples avec code, etc, ) par l'url : http://qt-project.org/doc/qt-4.8/ Logiciel libre pour développer des applications gratuites (licence GPL) sous la famille d Unix (installation comprise dans celle de Linux des distributeurs comme Red Hat, Fedora, Debian, etc, ) et payant sinon. A télécharger de http://qt.digia.com 3

Un éventail assez large de widgets et d outils pour traiter les images, pour les dialogues, pour imprimer, pour l OpenGL* (2D-3D), etc, A la place des réflexes (Callbacks), Qt propose les méthodes de traitement d événements et surtout les signaux-slots (voir le chapitre 2. ci-dessous). Si un slot (une procédure) est connecté à un signal (une autre procédure) et si ce signal est émis, le noyau Qt se charge automatiquement d exécuter ce slot. Les signaux ne sont pas des événements. Par exemple : - Une widget de la classe QPushButton émet son signal clicked() lorsqu elle reçoit un événement ButtonPress suivi d un ButtonRelease, mais aussi des touches claviers accélératrices appropriées si le bouton en est sensibilisé. - Un objet (de la classe QObject) émet son signal destroyed() avant qu il soit détruit. N importe qui peut émettre un signal. * OpenGL est une marque déposée de Silicon Graphics 4

Comme pour les classes MFC (Windows/Microsoft), un certain nombre de classes de widget possèdent des méthodes virtuelles liées aux événements. Elles sont automatiquement appelées en réaction aux événements reçus : Dans la classe QWidget, on trouve les méthodes virtual void mousepressevent (QMouseEvent *); virtual void mousemoveevent (QMouseEvent *);... On peut donc hériter de cette classe en redéfinissant ces méthodes pour traiter ces événements. Pour aider le développeur, l outil qmake-qt4 permet de créer dans des cas courants un fichier projet (suffixé en général par.pro) ou un Makefile avec tous les liens nécessaires à partir d un fichier projet. Par exemple, en regroupant tous les sources (.h et.cpp) dans un répertoire (comme pour tous les exemples de ce cours), il suffit d y exécuter les commandes suivante : - qmake-qt4 project créer un fichier.pro - qmake-qt4 créer un Makefile à partir du fichier.pro. 5

Un premier exemple : (exemple0.cpp) /********** exemple0.cpp **********/ <qapplication.h> <qpushbutton.h> int main(int argc, char **argv) QApplication appli(argc, argv); /* ouverture session */ QPushButton bonjour("bonjour Monde!");/* sans mere, c est donc */ bonjour.resize(100, 30); /* une widget principale */ QPushButton hello("hello World!", NULL); /* sans mere, c est */ hello.resize(100, 30); /* aussi une widget principale */ hello.show(); bonjour.show(); /* on affiche les deux */ return appli.exec(); /* retour selon resultat de l execution */ 6

1. Widget Historique : (Xt / X Window System) - Serveur X : un processus qui contrôle les périphériques : écran(s), clavier, souris, tablette, etc, crée et gère physiquement les fenêtres, répond aux requêtes des clients : création de fenêtres, affichage, dessin, etc, leur envoie des événements. - Client X : une application X Window System. Il peut demander au serveur de créer 0, 1 ou plusieurs fenêtres principales «top level». Dans chacune d elles, il peut demander au serveur de créer d autres fenêtres filles, etc, On parlera d arbres de fenêtres avec au sommet de chaque arbre une fenêtre principale. - Gestionnaire de fenêtre : un client X qui gère votre(s) écran(s) en plaçant les fenêtres principales de votre application, en les décorant avec des bordures vous permettant de modifier leur taille, en y mettant une barre 7

de titre avec un bouton de fermeture, d agrandissement maximal, d iconification, etc, - Widget (composant d interface) = Window (fenêtre) + Gadget (ensemble de procédures et de structures de données pour la fenêtre). - Sous Motif, un gadget est un composant d interface sans fenêtre propre. Pour s afficher, il utilise la fenêtre de ses antécédents. - Une widget «top level» est une widget dont la fenêtre est «top level». - Comme pour l arbre de fenêtres, on parle d arbre de widgets. - Un composant sans fenêtre propre consomme moins de ressource (mémoire), forme plus exotique, mais réclame un peu plus de calcul. Java : - AWT : composants avec fenêtre, - Swing : composants dont une majorité sans fenêtre. Qt : - Widget : composants dont une majorité sans fenêtre. - Une widget déclarée sans parent (en utilisant le constructeur sans argument) est une widget «top level». Qt lui accorde une fenêtre «top level». 8

/********** exemple1.cpp **********/ <qapplication.h> <qwidget.h> <iostream> QWidget * fenetreracine (QWidget *w) QWidget *res = w; QWidget *parent = w->parentwidget(); while (parent!= NULL) res = parent; parent = res->parentwidget(); return res; void tracearbre (QWidget *w, int tab = 0) QList<QWidget *> liste = w->findchildren<qwidget *>(); QWidget *aux; 9

for (int i = tab; i > 0; --i) std::cout << "\t"; std::cout << w->objectname().toascii().data() << "\n"; while (!liste.isempty()) aux = liste.takefirst(); if (aux->parentwidget() == w) tracearbre(aux, tab + 1); int main(int argc, char *argv[]) QApplication appli(argc, argv); QWidget *principale = new QWidget(); principale->setwindowtitle("exemple1"); principale->setobjectname("principale"); /* ouverture session */ /* conteneur */ /* laisser un titre */ QWidget *fils_1 = new QWidget(principale); fils_1->setobjectname("fils_1"); 10

QWidget *petit_fils_1_1 = new QWidget(fils_1); petit_fils_1_1 ->setobjectname("petit_fils_1_1"); QWidget *petit_fils_1_2 = new QWidget(fils_1); petit_fils_1_2->setobjectname("petit_fils_1_2"); QWidget *fils_2 = new QWidget(principale); fils_2->setobjectname("fils_2"); QWidget *petit_fils_2 = new QWidget(fils_2); petit_fils_2->setobjectname("petit_fils_2"); std::cout << "\narbre à partir de principale :\n"; tracearbre(principale); std::cout << "\narbre à partir de la fenêtre racine " << "de principale :\n"; tracearbre(fenetreracine(principale)); std::cout << "\narbre à partir de la fenêtre racine " << "de petit_fils_2 :\n"; tracearbre(fenetreracine(petit_fils_2)); return appli.exec(); 11

$ Exemple1 Arbre à partir de principale : Principale Fils_1 Petit_Fils_1_1 Petit_Fils_1_2 Fils_2 Petit_Fils_2 Principale Petit_Fils_2 Fils_2 Petit_Fils_1_2 Petit_Fils_1_1 Fils_1 Arbre à partir de la fenêtre racine de principale : Principale Fils_1 Petit_Fils_1_1 Petit_Fils_1_2 Fils_2 Petit_Fils_2 Arbre à partir de la fenêtre racine de petit_fils_2 : Principale Fils_1 Petit_Fils_1_1 Petit_Fils_1_2 Fils_2 Petit_Fils_2 12

2. Signal et slot Utilisation Les signaux et slots sont des méthodes C++. Certaines classes de Widget contiennent un ou plusieurs signaux et/ou un ou plusieurs slots (voir la documentation sur les classes), par exemple : QAbstractButton : Slots void void... Signaux void void void void QPushButton : (héritée de QAbstractButton) Slot void showmenu () animateclick () toggle () et les signaux et slots hérités de sa mère pressed () released () clicked () toggled ( bool on ) et les signaux et slots hérités de sa mère 13

Pour connecter un slot à un signal : Bool connect const const const const QObject::connect( ) /* la forme couramment utilisée */ ( QObject char QObject char * * * * emetteur, /* l objet qui émet le du_signal, /* signal dont le slot du receveur, /* receveur va être connecté, et_son_slot ); */ */ */ Il y a d autres signatures de QObject::connect(). Comme le signal (resp. slot) est une méthode, on utilise le macro SIGNAL() (resp. SLOT()) pour entourer le signal (resp. slot) dans connect(). Un slot et un signal ne renvoient aucune valeur (type void). Pour être propre, on doit connecter un slot à un signal ayant la même signature. On peut connecter un nombre quelconque de slots à un signal donné. Un slot peut être connecté à un nombre quelconque de signaux. 14

Pour déconnecter un slot à un signal : Bool disconnect ( const QObject const char const QObject const char QObject::disconnect( ) /* la forme couramment utilisée */ * * * * emetteur, /* l objet qui émet le */ du_signal, /* signal dont le slot du */ receveur, /* receveur va être déconnecté, */ et_son_slot ); Il y a d autres signatures de QObject::disconnect(). Comme le signal (resp. slot) est une méthode, on utilise le macro SIGNAL() (resp. SLOT()) pour entourer le signal (resp. slot) dans disconnect(). 15

On quitte avec notre exemple légèrement modifié : (exemple2_1.cpp) /********** exemple2_1.cpp **********/ <qapplication.h> <qpushbutton.h> int main(int argc, char **argv) QApplication appli(argc, argv); /* ouverture session */ QPushButton *bonjour = new QPushButton("Bonjour Monde!", NULL); bonjour->resize(100, 30); QObject::connect( bonjour, SIGNAL(clicked()), &appli, SLOT(quit())); bonjour->show(); return appli.exec(); 16

Un autre exemple : (exemple2_2.cpp) /********** exemple2_2.cpp **********/ <qapplication.h> <qwidget.h> <qslider.h> <qlabel.h> int main(int argc, char *argv[]) QApplication appli(argc, argv); QWidget *principale = new QWidget(); principale->setwindowtitle("exemple2_2"); principale->setgeometry(0, 0, 150, 90); QSlider *reglette = new QSlider( Qt::Horizontal, principale); reglette->setrange(1, 12); reglette->setsinglestep(1); 17 /* ouverture session */ /* conteneur, sans mere, donc principal */ /* laisser un titre */ /* x, y, larg. et haut. */ /* une reglette */ /* en horizontale */ /* comme mere */ /* valeur minimale, maximale */ /* par pas de 1 pour les les touches flèches */

reglette->setsliderposition(9); reglette->setgeometry(10, 10, 130, 30); /* valeur initiale */ QLabel *affichage = new QLabel(principale); affichage->setgeometry(10, 60, 130, 30); affichage->setalignment(qt::alignhcenter); affichage->setnum(9); QObject::connect( reglette, SIGNAL(valueChanged(int)), affichage, SLOT(setNum(int))); principale->show(); return appli.exec(); 18

Pour ajouter de nouveaux signaux et slots, on définit une nouvelle classe : Dans un fichier d en-tête.h (par exemple, monlabel.h), définir une nouvelle classe héritant de la classe QObject ou de ses sous-classes, utiliser le macro Q_OBJECT et les mots clés signals et slots. Fichier monlabel.h ne contenant rien d autre que la classe : /********** monlabel.h **********/ #ifndef MONLABEL_H #define MONLABEL_H <qlabel.h> <qstring.h> class MonLabel : public QLabel Q_OBJECT public : MonLabel (const QString texte, QWidget *parent, Qt::WindowFlags f = 0); 19

public slots : void slotsetmois (int); signals : void signalfin (); private : QString *lesmois[12]; ; #endif On exécute après la commande moc -o signal_slot_monlabel.cpp monlabel.h qui générera le fichier signal_slot_monlabel.cpp à partir du contenu du fichier monlabel.h. On y trouve tous les ingrédients utilisés pour la connexion. moc est automatiquement fait par qmake-qt4. Dans le fichier monlabel.cpp, on écrit les slots et autres méthodes pour la classe MonLabel : 20

/********** monlabel.cpp **********/ "monlabel.h" MonLabel::MonLabel (const QString texte, QWidget * parent, Qt::WindowFlags f) : QLabel(texte, parent, f) const char *nomsmois[] = "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" ; for (int i = 0; i < 12; ++i) lesmois[i] = new QString(nomsmois[i]); void MonLabel::slotSetMois (int k) if (k == 13) emit signalfin(); else settext(*lesmois[k-1]); 21

Ne pas définir les méthodes concernant les signaux car moc les a déjà faits dans signal_slot_monlabel.cpp à sa façon pour être compatibles avec la connexion connect(). Sinon, il y aura alors une erreur de re-définition à la compilation finale. Reste maintenant à l utiliser en modifiant légèrement le programme précédent : (exemple2_3.cpp) /********** exemple2_3.cpp **********/ <qapplication.h> <qwidget.h> <qslider.h> "monlabel.h int main(int argc, char *argv[]) QApplication appli(argc, argv); QWidget *principale = new QWidget(); principale->setwindowtitle("exemple2_3"); principale->setgeometry(0, 0, 150, 90); 22 /* ouverture session */ /* conteneur, sans mere, donc principal */ /* laisser un titre */ /* x, y, larg. et haut. */

QSlider *reglette = new QSlider( Qt::Horizontal, principale); reglette->setrange(1, 13); reglette->setsinglestep(1); reglette->setsliderposition(9); reglette->setgeometry(10, 10, 130, 30); /* une reglette */ /* en horizontale */ /* comme mere */ /* valeur minimale, maximale */ /* par pas de 1 pour les les touches flèches */ /* valeur initiale */ MonLabel *affichage = new MonLabel("Septembre", principale); affichage->setgeometry(10, 60, 130, 30); affichage->setalignment(qt::alignhcenter); QObject::connect( reglette, SIGNAL(valueChanged(int)), affichage, SLOT(slotSetMois(int))); QObject::connect( affichage, SIGNAL(signalFin()), &appli, SLOT(quit())); principale->show(); return appli.exec(); 23

En déplaçant le curseur au delà du mois de décembre, on quitte l application. Il est possible de connecter un signal à un autre signal : ajouter le signal signalsuite() dans monlabel.h. dans monlabel.cpp, mettre emit signalsuite(); à la place de emit signalfin();, ajouter aux connections ci-dessus connect() une nouvelle : QObject::connect(affichage, SIGNAL(signalSuite()), affichage, SIGNAL(signalFin())); et on aura le même résultat. 24

3. Evénements Méthodes prédéfinies (event handler) Un traitement d'événement ("event handler") est une méthode (procédure) appelée par la couche Qt lorsque certain type d événement (ou suite d événements) se produit dans la fenêtre d une widget. Par exemple, pour la classe QWidget, une partie des méthodes membres réagissant aux événements particuliers sont : virtual virtual virtual virtual virtual... bool void void void void event mousepressevent mousereleaseevent mousedoubleclickevent mousemoveevent (QEvent *); (QMouseEvent (QMouseEvent (QMouseEvent (QMouseEvent *); *); *); *); Presque tous les événements concernant une fenêtre sont représentés. On a en plus des traitements pour une suite d événements comme mousedoubleclickevent(). 25

Et plus encore : virtual virtual virtual virtual... void void void void dragenterevent dragmoveevent dragleaveevent dropevent (QDragEnterEvent *); (QDragMoveEvent *); (QDragLeaveEvent *); (QDropEvent *); La classe QWidget est la classe de base héritée par toutes les classes de widget. On retrouve donc tous ces traitements d événements dans ses sous-classes. Par exemple : exemple3_1.cpp /********** exemple3_1.cpp **********/ <qapplication.h> <qwidget.h> <qevent.h> <qlabel.h> <stdio.h> 26

class MonWidget : public QWidget QLabel *lx, *ly; public : MonWidget () : QWidget() void setxy (QLabel *x, QLabel *y) lx = x; ly = y; protected : void mousemoveevent (QMouseEvent *e); ; /* avec bouton enfonce sinon */ /* voir setmousetracking() */ int main(int argc, char *argv[]) QApplication appli(argc, argv); /* ouverture session */ MonWidget *principale = new MonWidget(); principale->setgeometry(0, 0, 150, 90); principale->setwindowtitle("exemple3_1"); /* conteneur */ /* x, y, larg. et haut. */ /* laisser un titre */ QLabel *x = new QLabel(principale); x->setgeometry(10, 60, 60, 30); x->setalignment(qt::alignleft); x->settext("x = 0"); 27

QLabel *y = new QLabel(principale); y->setgeometry(80, 60, 60, 30); y->setalignment(qt::alignleft); y->settext("y = 0"); principale->setxy(x, y); principale->show(); return appli.exec(); void MonWidget::mouseMoveEvent (QMouseEvent *e) char chaine[200]; sprintf(chaine, "x = %d", e->x()); lx->settext(chaine); sprintf(chaine, "y = %d", e->y()); ly->settext(chaine); 28

Le traitement d événements event() est très particulier : appelé en premier, passe par tous les filtres installés (voir Filtres ci-dessous), s il n y a aucun filtre concernant cet événement, il appellera le traitement correspondant à l événement. il est donc déconseillé de le redéfinir dans les sous-classes, mais plutôt de redéfinir les traitements correspondant aux événements. Lorsque l on redéfinit dans une sous-classe un traitement d événement, il est souvent nécessaire d appeler le même traitement d événement de sa sur-classe : exemple3_2.cpp /********** exemple3_2.cpp **********/ <qapplication.h> <qpushbutton.h> class MonBouton : public QPushButton public : MonBouton (const QString &text, QWidget *parent) : QPushButton(text, parent) 29

protected : virtual void mousereleaseevent (QMouseEvent *e); ; void MonBouton::mouseReleaseEvent (QMouseEvent *e) QPushButton::mouseReleaseEvent(e); int main(int argc, char **argv) QApplication appli(argc, argv); /* ouverture session */ MonBouton *bonjour = new MonBouton("Bonjour Monde!", NULL); bonjour->resize(100, 30); QObject::connect( bonjour, SIGNAL(clicked()), &appli, SLOT(quit())); bonjour->show(); return appli.exec(); 30

Si on ne fait pas un appel au traitement de la sur-classe (c est à dire si on enlève du traitement d événement MonBouton::mouseReleaseEvent() la ligne QPushButton::mouseReleaseEvent()), alors le signal clicked() qui est émis par défaut par QPushButton::mouseReleaseEvent() ne sera plus émis et le slot quit() de l application ne sera pas appelé. L affichage aussi est affecté par cet absence. Filtres d événements Déclarer une classe MonFiltre héritant de QObject, et redéfinir la méthode eventfilter() : Class MonFiltre : public QObject protected : bool eventfilter (QObject *o, QEvent *e)... return true; /*... return false; 31

Le traitement d événement event() passe voir tous les filtres installés dont celuici. La valeur de retour est très importante : true pour signifier que l événement est traité par ce filtre et event() passera voir les autres filtres, mais ne passera plus au traitement d événement correspondant, false pour signifier le contraire, et si tous les filtres renvoient false (aucun filtre n est donc intéressé) alors event() passera voir le traitement d événement correspondant. Installer le filtre sur la widget avec QObject::installEventFilter(). Un exemple : exemple3_3.cpp /********** exemple3_3.cpp **********/ <qapplication.h> <qwidget.h> <qevent.h> <qlabel.h> <iostream> 32

class MonFiltre : public QObject protected : bool eventfilter (QObject *o, QEvent *e); ; class MonWidget : public QWidget public : QLabel *lx, *ly; MonWidget () : QWidget() void setxy (QLabel *x, QLabel *y) lx = x; ly = y; protected : void mousepressevent (QMouseEvent *e); void mousereleaseevent (QMouseEvent *e); void mousemoveevent (QMouseEvent *e); ; int main(int argc, char **argv) QApplication appli(argc, argv); /* ouverture session */ MonWidget *principale = new MonWidget(); /* conteneur */ principale->setgeometry(0, 0, 150, 90); /* x, y, larg. et haut. */ 33

principale->setwindowtitle("exemple3_3 ); QLabel *x = new QLabel(principale); x->setgeometry(10, 60, 60, 30); x->setalignment(qt::alignleft); x->settext("x = 0"); QLabel *y = new QLabel(principale); y->setgeometry(80, 60, 60, 30); y->setalignment(qt::alignleft); y->settext("y = 0"); MonFiltre *monfiltre = new MonFiltre(); principale->setxy(x, y); principale->installeventfilter(monfiltre); principale->show(); return appli.exec(); void MonWidget::mousePressEvent (QMouseEvent *e) std::cout << "ButtonPress\n"; 34

void MonWidget::mouseReleaseEvent (QMouseEvent *e) std::cout << "ButtonRelease\n"; Void MonWidget::mouseMoveEvent (QMouseEvent *e) std::cout << "Ne passera jamais par ici\n"; bool MonFiltre::eventFilter (QObject *o, QEvent *e) char chaine[200]; if (e->type() == QEvent::MouseMove) sprintf(chaine, "x = %d", ((QMouseEvent *)e)->x()); ((MonWidget *)o)->lx->settext(chaine); sprintf(chaine, "y = %d", ((QMouseEvent *)e)->y()); ((MonWidget *)o)->ly->settext(chaine); return true; else return false; 35

A l exécution, on remarquera que le traitement d événement MonWidget::mouseMoveEvent() ne sera pas appelé par event() puisque notre filtre retroune true pour l événement MouseMove. Et si dans MonFiltre::eventFilter() à la place de return false on retournait return true, auriez-vous deviner le résultat? Aucun traitement d événement n est appelé : plus de ButtonPress, de ButtonRelease, d Expose, etc, Seul le MouseMove est traité par le filtre. Quelques traitements d événement particuliers appelés par QWidget::event() (si aucun filtre n est intéressé par ces événements) QEvent::MouseButtonPress void QWidget::mousePressEvent (QMouseEvent *e); QEvent::Leave void QWidget::leaveEvent (QEvent *e); QEvent::Close void QWidget::closeEvent (QCloseEvent *e);... 36

virtual void QWidget::mousePressEvent (QMouseEvent *e); Il y a un comportement par défaut pour cette méthode, entre autre, elle exécute e->accept(). Si on réécrit cette méthode en y mettant e->ignore(), l événement sera transmis à la widget mère. virtual void QWidget::closeEvent (QCloseEvent *e); Par exemple, cet événement est reçu par la widget principale lorsque l utilisateur clique dans le bouton de fermeture situé dans la barre supérieure de décoration. Il y a un comportement par défaut pour cette méthode, entre autre, elle exécute e->accept() qui fermera définitivement la fenêtre, Pour ne pas fermer définitivement la widget, on peut réécrire cette méthode soit en y mettant e->ignore(), soit en omettant e->accept() et e->ignore(). 37

Un exemple qui permet de fermer la fenêtre au bout de 10 clics dans le bouton : /********** exemple3_4.cpp **********/ void QWidget::closeEvent (QCloseEvent *e) static int i = 9; <qapplication.h> <qpushbutton.h> <qevent.h> if (!i--) e->accept(); else e->ignore(); int main(int argc, char **argv) QApplication appli(argc, argv); QPushButton bonjour("bonjour Monde!", NULL); bonjour.resize(100, 30); bonjour.show(); return appli.exec(); 38

Send & Post On peut aussi envoyer un événement à une widget par bool QApplication::sendEvent (QObject *receveur, QEvent *event ); méthode static qui envoie directement au receveur et attend que l événement soit traité. void QApplication::postEvent (QObject * receveur, QEvent * event ) méthode static qui se contente de ranger l événement dans la file d événements du receveur sans attendre la fin du traitement. 39

4. Dessin Algorithme du peintre, Double buffering (depuis la version 4) : emprunté de OpenGL, DirectX, etc,, meilleur affichage, animation plus fluide, QPainter : classe qui fournit les outils de dessins de bas niveau. Elle permet de dessiner dans les classes héritées de QPaintDevice : QPixmap, QWidget, QPicture, QPrinter, etc, On dessine à la façon Windows entre le begin() et le end() : bool QPainter::begin (QPaintDevice *device); appelé automatiquement par le constructeur QPainter::QPainter (QPaintDevice *device);, sur un support (device) donné, un seul begin() jusqu au end() ou jusqu à la destruction de ce QPainter, renvoie true s il peut dessiner sur le support device, false sinon. 40

bool QPainter::end (); appelé automatiquement par le destructeur de QPainter, renvoie true s il n est plus active, false sinon. Quelques méthodes de QPainter : - QRectF boundingrect ( const QRectF &rectangle, /* cadre */ int flags, /* alignement du texte */ const QString &text); renvoie le rectangle envelopant du text. - void drawarc (int x, int y, int width, int height, int startangle, /* positive = sens trigonométrique */ int spanangle); - void drawimage ( const QRectF &rectangle, const QImage &image); /* dessine l image en se limitant dans un rectangle */ - void drawtext (const QPointF &position, const QString &text); 41

- void fillrect ( const QRect &rectangle, const QBrush &brush); - void setclipping (bool enable); /* en évitant ou pas les filles */ - void setpen (const QPen &pen); void setbrush (const QBrush & brush); - void setpen (const QColor & color); /* changer la couleur */ - void setopacity (qreal opacity); /* 0.0 = transparent et 1.0 = opaque */ - void setbackground (const QBrush &brush); /* utilisé pour dessiner les creux des traits en pointillés ou le fond des caractères */ - void rotate (qreal angle); /* rotation du repère sens horaire */ void scale (qreal sx, qreal sy); /* changement d échelle */ - void save (); /* empiler les caractéristiques de ce painter */ void restore (); /* et les restituer */ 42

Par exemple : exemple4.cpp /********** exemple4.cpp **********/ <qapplication.h> <qwidget.h> <qpainter.h> <QLinearGradient> class MaWidget : public QWidget protected : void paintevent (QPaintEvent *e); ; int main(int argc, char **argv) QApplication appli(argc, argv); MaWidget *principale = new MaWidget(); principale->setgeometry(0, 0, 150, 90); principale->setwindowtitle("exemple4"); principale->show(); 43

return appli.exec(); void MaWidget::paintEvent (QPaintEvent *e) QPainter peintre; QLinearGradient gradient(50, 50, 200, 200); peintre.begin(this); peintre.setpen(qt::blue); peintre.drawtext(50, 20, "Exemple4"); gradient.setcolorat(0, Qt::green); gradient.setcolorat(1, Qt::red); peintre.setpen(qpen(gradient, 10)); peintre.setfont(qfont("helvetica", 50, QFont::Bold)); for (int i = 100; i < 200; i += 40) peintre.drawtext(50, i, "Exemple4"); peintre.drawline(50, 50, 200, 200); peintre.drawline(50, 200, 200, 50); peintre.end(); 44

5. Menu Classe des barres de menus : QMenuBar. Une widget de la classe QMainWindow détecte automatiquement les widgets filles des classes QMenuBar, QToolBar et QStatusBar. Elle permet d organiser une barre de menus, un nombre quelconque de barres d outils, une barre d état et une widget centrale. On utilise les slots pour donner des comportements aux différents boutons des menus. Pour une barre de menus avec menus déroulants : /********** mamainwindow.h **********/ #ifndef MAMAINWINDOW_H #define MAMAINWINDOW_H <QMainWindow> <QMenuBar> <QStatusBar> <QAction> <QContextMenuEvent> 45

class MaMainWindow : public QMainWindow Q_OBJECT public : MaMainWindow (); private : QMenuBar *menubar; QMenu *fmenu, *emenu; QAction *actione1, *actione2; protected : void contextmenuevent (QContextMenuEvent *event); private slots : void slotf1 (); void slotf2 (); void slote1 (); void slote2 (); ; #endif 46

"mamainwindow.h" <qapplication.h> <iostream> MaMainWindow::MaMainWindow () QAction *action; statusbar(); // rend la barre de status du MainWindow, // la créer si elle n'existe pas (par défaut). fmenu = menubar()->addmenu(tr("&fichier")); action = new QAction(tr("F&1"), this); action->setshortcut(tr("ctrl+1")); action->setstatustip(tr("action F1")); connect(action, SIGNAL(triggered()), this, SLOT(slotF1())); fmenu ->addaction(action); action = new QAction(tr("F&2"), this); action->setshortcut(tr("ctrl+2")); action->setstatustip(tr("action F2")); connect(action, SIGNAL(triggered()), this, SLOT(slotF2())); fmenu->addaction(action); fmenu->addseparator(); 47

action = new QAction(tr("&Quitter"), this); action->setshortcut(tr("ctrl+shift+q")); action->setstatustip(tr("action Quitter")); connect(action, SIGNAL(triggered()), this, SLOT(close())); fmenu->addaction(action); emenu = menubar()->addmenu(tr("&edition")); action = new QAction(tr("E&1"), this); action->setshortcut(tr("ctrl+3")); action->setstatustip(tr("action E1")); connect(action, SIGNAL(triggered()), this, SLOT(slotE1())); emenu ->addaction(action); actione1 = action; action = new QAction(tr("E&2"), this); action->setshortcut(tr("ctrl+4")); action->setstatustip(tr("action E2")); connect(action, SIGNAL(triggered()), this, SLOT(slotE2())); emenu->addaction(action); actione2 = action; 48

void MaMainWindow::contextMenuEvent (QContextMenuEvent *event) static QMenu *menu = NULL; if (menu == NULL) menu = new QMenu(this); menu->addaction(actione1); menu->addaction(actione2); menu->exec(event->globalpos()); void void void void MaMainWindow::slotF1 MaMainWindow::slotF2 MaMainWindow::slotE1 MaMainWindow::slotE2 () () () () std::cout std::cout std::cout std::cout 49 << << << << "F1\n"; "F2\n"; "E1\n"; "E2\n";

6. Placement Par position, QHBoxLayout : placer les widgets filles en horizontal (exemple6_1.cpp) /********** exemple6_1.cpp **********/ <qapplication.h> <qwidget.h> <qpushbutton.h> <qlayout.h> int main(int argc, char **argv) QApplication appli(argc, argv); QWidget *principale = new QWidget(); principale->setgeometry(0, 0, 150, 90); principale->setwindowtitle("exemple6_1"); 50 /* ouverture session */ /* conteneur */ /* x, y, larg. et haut. */

QHBoxLayout *placement = new QHBoxLayout(principale); placement->addwidget(new QPushButton("Bouton 1", principale)); placement->addwidget(new QPushButton("Bouton 2", principale)); placement->addwidget(new QPushButton("Bouton 3", principale)); placement->activate(); (new QPushButton("Bouton 0", principale)) ->setgeometry(0, 0, 100, 40); principale->show(); return appli.exec(); QVBoxLayout : même chose, mais en vertical. En combinant les deux : (exemple6_3.cpp) 51

/********** exemple6_3.cpp **********/ <qapplication.h> <qwidget.h> <qpushbutton.h> <qlayout.h> int main(int argc, char **argv) QApplication appli(argc, argv); QWidget *principale = new QWidget(); principale->setgeometry(0, 0, 150, 90); principale->setwindowtitle("exemple6_3"); /* ouverture session */ /* conteneur */ /* x, y, larg. et haut. */ QVBoxLayout *placementv = new QVBoxLayout(principale); QHBoxLayout *placementh1 = new QHBoxLayout(); QHBoxLayout *placementh2 = new QHBoxLayout(); placementv->addlayout(placementh1); placementv->addlayout(placementh2); 52

placementh1->addwidget(new placementh1->addwidget(new placementh2->addwidget(new placementh2->addwidget(new placementh2->addwidget(new QPushButton("Bouton QPushButton("Bouton QPushButton("Bouton QPushButton("Bouton QPushButton("Bouton 1-1", 1-2", 2-1", 2-2", 2-3", principale)); principale)); principale)); principale)); principale)); principale->show(); return appli.exec(); QGridLayout : (exemple6_4.cpp) /********** exemple6_4.cpp **********/ <qapplication.h> <qwidget.h> <qpushbutton.h> <QGridLayout> 53

int main(int argc, char **argv) QApplication appli(argc, argv); QWidget *principale = new QWidget(); principale->setgeometry(0, 0, 150, 90); principale->setwindowtitle("exemple6_4"); /* ouverture session */ /* conteneur */ /* x, y, larg. et haut. */ QGridLayout *placement = new QGridLayout(principale); placement->addwidget(new placement->addwidget(new placement->addwidget(new placement->addwidget(new placement->addwidget(new QPushButton("Bouton QPushButton("Bouton QPushButton("Bouton QPushButton("Bouton QPushButton("Bouton 1, 1, 1, 2); 1", 2", 3", 4", 5", principale), principale), principale), principale), principale), 0, 0, 0, 1, 0); 1); 2); 0); principale->show(); return appli.exec(); QStackedLayout : afficher une widget à la fois (exemple6_5.cpp) 54

7. Quelques classes QObject : classe de base pour tous les widgets. On y trouve outils pour gérer l arborescence des objets, signaux, slots, connect et disconnect, nom pour chaque objet qui permet de le retrouver facilement par nom, outils pour traiter les événements, QPaintDevice : classe de base pour les objets où on peut dessiner, QWidget : héritée de QObject et de QPaintDevice, QPixmap : hérité seulement de QPaintDevice, dédiée pour l affichage à l écran, pas d hiérarchie, pas de traitement d événement, juste un espace (de mémoire) où on peut dessiner, non affichable directement sur l écran. Pour ce faire, il faut le copier dans une widget, QImage : hérité seulement de QPaintDevice, plus sofistiquée que QPixmap, entrées et sorties vers les fichiers en formats JPEG, GIF, PNG, etc., 55

QPrinter et QPrintDialog /********** exemple7_1.cpp **********/ <QApplication> <QPainter> <QPrinter> <QPrintDialog> int main(int argc, char **argv) QApplication appli(argc, argv); /* ouverture session */ QPrinter *imp = new QPrinter(); QPrintDialog *imp_dial = new QPrintDialog(imp); QPainter *peintre = new QPainter(); if (imp_dial->exec() == QDialog::Accepted) // ouvre le dialogue et attend peintre->begin(imp); // la réponse peintre->drawellipse(100, 100, 100, 100); peintre->end(); return appli.exec(); 56

QGLWidget : Widget dédié à l OpenGL une fois la widget mise en place, on peut utiliser toutes les fonctions et procédures d OpenGL. Exploite pleinement la possibilité physique de la carte graphique. Création plus facile de menus et de dialogues. 57

QColorDialog : /********** exemple7_3.cpp **********/ <QApplication> <QColorDialog> <QColor> <iostream> int main(int argc, char **argv) QApplication appli(argc, argv); /* ouverture session */ QColorDialog *color_dial; QColor c = color_dial->getcolor(); if (c.isvalid()) std::cout << "Vous avez << "Rouge = " << "Vert = " << "Bleu = " return appli.exec(); choisi la couleur dont les composées :\n" << c.red() << "\n" << c.green() << "\n" << c.blue() << "\n"; 58

QFileDialog : /********** exemple7_4.cpp **********/ <QApplication> <QFileDialog> <iostream> int main(int argc, char **argv) QApplication appli(argc, argv); /* ouverture session */ QString f = QFileDialog::getOpenFileName(NULL, "Ouverture de fichier", "."); // getsavefilename(); std::cout << f.tostdstring() << "\n"; return appli.exec(); 59

QRubberBand : permet d afficher un rectangle ou un trait horizontal ou vertical de sélection dynamique. QMovie QSvgWidget : permet d afficher les contenus SVG (Scalable Vector Graphics), l équivalent de Flash (Flash Player de chez Abobe). QXmlReader : un interface pour XML. QTextBrowser : permet d afficher des hypertextes et d y naviguer. QPixmap : exactement comme une fenêtre, on peut y dessiner. etc, 60