Introduction à gtkmm 2.4 Plan de cours 1. Vision d'ensemble 2. Gestion des évènements 3. Présentation des widgets
1 2 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Ce qui ne sera pas traité (en particulier) Vision d'ensemble
Gtk+ (version C)
Les détails des librairies sœurs la Glib / Glibmm : Gestion de mémoire, types particuliers, entrées-sorties, ... Cairo, Pango
Détails de la libsigc 1. Introduction 2. Historique et position actuelle de Gtkmm Gestion des erreurs et du logging 3. Organisation des librairies de Gtkmm Internationalisation 4. Outils de développement Les Tree View (pas de MVC en Gtk !) 5. Conventions de programmation de Gtkmm 6. Les basiques Le parsing XML
Comment créer une bonne interface ... 3 4 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
gtkmm Gtkmm vs Qt (by Gtkmm developers)
Gtkmm does things in a more C++ way . Binding C++ de Gtk (Gtkmm = Gtk--) Qt has it's own Qt-specific containers, gtkmm uses std::string, std::list, std::vector, Gtk+ : en C mais basé sur des concepts objet iterators, etc. It therefore duplicates a lot of stuff that is now in the standard library, such as containers and type information. Ensemble de librairies pour la programmation Gtkmm was able to use standard C++ to provide signals without changing the C+ + d'interfaces graphiques language. gtkmm uses pure C++. Qt requires extensions to C++ that are parsed by the moc pre-processor. Most significantly, they modified the C++ language to provide Développé et maintenu par GNOME Foundation signals, so that Qt classes can not be used easily with non-Qt classes. Sous licence LGPL 2.1 With gtkmm normal C++ memory management can be used. Qt demands that all widgets are dealt with as pointers, and that deletion of widgets is surrendered to http://www.gtkmm.org parent widgets. Téléchargements Arrangement of widgets seems to be simpler in gtkmm . In Qt, Containers and Layouts are separate classes, and child widgets must be added to both. Documentations The gtkmm API tends to be more explicit . The behaviour of Qt classes is often Qqs tutoriaux dependent upon the implicit effects of confusingly-overridden constructors. Also, Gtkmm and the other *mm modules allow you to build software which works more closely with the GNOME desktop . 5 6 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Look and feel Historique Bureau GNOME 1997 : gtk+ 1.0 (Mattis, Kimball & MacDonald) U. Californie, Berkeley Projet initié par la conception de GIMP GTK = GIMP Tools Kit
1998 : gtk+ 1.2 et gtkmm 1.2
1998 : gtk+ 2.0 (620,000 lignes) et gtkmm2.0 Pango, GdkPixbuf, ATW Nouveaux Widget (Texte et Tree),
2005 : Apparition de Cairo 1.0
Gnumeric sous Windows 7 8 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Situation actuelle Librairies usuelles
Communauté de développement de Gtk active Gtk ne réimplémente pas les structures usuelles de
Toujours utilisée par GIMP programmation objet Différence avec Qt Librairie graphique utilisée pour GNOME, Xcfe Utilise la librairie standard C++ (STL) Encore assez largement utilisée Container ( vector , list , map , ...) Iterator et algorithm Version actuelle assez abouti et stable Sauf pour les String (utiliser les Glib:ustring !!) Vers une version 3 ??? Détail qui a son importance : l'un des rares défaut de STL est de ne pas gérer l'UTF-8 (accents, etc...) !
Toutes les librairies graphiques proposent leur version des string !
9 10 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Librairies associées de Gtkmm Organisation des
Pango/Pangomm librairies Gestion de l'affichage du texte
Gdk Primitives de dessin
Cairo / Cairomm Librairie de dessin vectoriel
Facile de s'y retrouver: Champs de compétence bien délimités Chaque librairie utilise son propre namespace
11 12 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
pkg-config pkg-config
pkg-config : outil de gestion des dépendances entre Très utile pour faciliter l'écriture des commandes de les librairies installées sur le système compilation sans oublier d'includes
La description de ces librairies se trouvent dans le
dossier : Compilation : /usr/lib/pkgcon gfi gcc -c `pkg-config --flagc gtkmm2.4` -o La commande suivante affiche tous les includes et fichier.o fichier.c librairies nécessaires à la compilation d’un fi chier
utilisation Gtkmm : Édition de liens : gcc `pkg-config --libs gtkmm2.4` -o main pkg-confi g --libs --c fl ags gtkmm-2.4 fichier.o
13 14 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Outils de développement Outils de développement
Interfaçage avec Eclipse CDT Glade cf. tutoriel en ligne pour la http://glade.gnome.org/ création d'un projet C++ Interface graphique pour sous Eclipse avec gestion créer simplement des des librairies Gtkmm. interfaces GTK+ Facilité de codage de Eclipse Existe pour Windows auto-complétion Alternative possible : Gazpacho
GObject Builder préprocesseur qui permet de construire des objets GObject
15 16 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Documentation Autres binds de Gtk+
En ligne : C++ : GtkMM
http://www.gtkmm.org/documentation.shtml C# : Gtk# API Java : Java-Gnome Documentation générale Python : PyGTK Exemples PHP : PHP-Gtk (partiel)
Ada, OCaml, R, Perl, ...
http://www.gtk.org/language-bindings.html 17 18 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Portabilité Licence
Peut être porté sur tout OS pouvant faire fonctionner un GTK+ est un projet libre : GNU LGPL 2.1 (Library serveur X (et disposant d'une version convenable de la General Public licence)
XLib) Les codes utilisant GTK+ ne doivent pas Sous GNU/Linux obligatoirement être licenciés GPL ! Sous Windows La LGPL exige uniquement de conserver la trace des Avec MinGW personnes ayant contribuer au code Compatibilité partielle (mais difficile) avec MSVC Valable aussi bien pour l'utilisation des librairies que du code Sous MacOS X source
Nouvellement possible avec Qt 4.5 !
19 20 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Introduction à Gtkmm Conventions de nommage
Nom des classes : Pas de préfixe (préfixé par le namespace !) ex: Button ou Gtk:: Button Attention : GtkButton réfère à la structure C d'un bouton dans la librairie Gtk+ Chaque « mot » commence par une majuscule
1. Historique et position actuelle de Gtkmm ex: Button, Text View, VB ox, Viewport, ... 2. Organisation des librairies de Gtkmm Nom des membres 3. Outils de développement et binds 4. Conventions de programmation de Gtkmm Commencent par « m_ » 5. Les basiques Mots avec majuscules, séparés par des « _ » ex : m_L abel _V alue(''Value :'');
Label contenu dans un widget
21 22 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Conventions de nommage Conventions de nommage
Méthodes Les handlers : commencent par le mot clé « on » Pas de majuscule ex : virtual void on_ clicked() Mots séparés par des « _ » Fonctions connectés aux signaux correspondants
Getter et setter Fonctions déclarées comme protégées Elles peuvent être surchargées lors de la conception de ses set : Commence par le mot clé « set » propres widgets qui héritent des widgets par existants ex. void set_ label (const Glib::ustring& label) Propriétés de l'interface (GLib) : commencent par le mot get : Commence par le mot clé « get » clé « property » ex. Glib::ustring get_ label() const ex : Glib::PropertyProxy_ReadOnly
23 24 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Les includes Introduction à Gtkmm
#include
Attention aux inclusions provenant des librairies sœurs #include
25 26 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Éléments basiques 1 : les widgets Éléments basiques 2 : les signaux
Un application Gtkmm est constituée de Fenêtres Gtkmm est basé sur les concepts de signal et de callback (windows) contenant des éléments d'interfaces (widgets) (ou handlers) tels que : des signaux peuvent être émis par les widgets lors boutons d'évènements comme un clic de souris boîtes de textes chaque widget a ses propres signaux qu'il peut émettre (dans la limite des signaux X !) ... les signaux peuvent être rattrapés pour être traités ( signal Chaque type de widget est représenté par une classe handlers ) Les widgets sont organisés graphiquement Les signaux de Gtkmm sont basés sur libsigc++ en ligne ou en colonne de widgets
m_button1.signal_clicked().connect( sigc::mem_fun(*this, &HelloWorld::on_button_clicked) ); 27 28 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Éléments basiques 2 : les signaux Conception d'une application Gtkmm
Comparaison avec Java/Swing 1. Conception de fenêtres et de widgets par la combinaison Java/Swing : principe de Listeners des widgets existants
m_button1.addActionListerner( new ActionListener() { Définition de la forme de l'interface public void actionPerformed(ActionEvent e) { system.out.println('coucou'); } 2. Conception des signal handlers }); Gtkmm : un handler est une fonction qui implémente un Définition des comportements potentiels de comportement à réaliser l'interfaces
m_button1.signal_clicked().connect( sigc::mem_fun(*this, 3. Connexions des signaux et signal handlers &HelloWorld::button_clicked) ); Description du comportement de l'interface en fonction des void HelloWorld::button_clicked() { évènements (actions de l'utilisateur) cout << 'coucou' << end; } 29 30 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Éléments basiques 3 : 1er programme Première classe d'une « interface »
#include
return Gtk::Main::run(window); Gtk::Main kit(argc, argv) : Objet Gtk::Main indispensable pour créer } une application Gtkmm Initialise Gtkmm Lit les arguments destinées aux appli. X ( e.g. options -display, -geometry)
Gtk::Window window : Créer un objet fenêtre
Gtk::Main::run(window) : Exécute la fenêtre comme fenêtre principale
31 32 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Première classe d'une « interface » Plan de cours maFenetre::maFenetre() : Gtk::Window() { 1. Vision d'ensemble set_title('Ma fenetre'); Gtk::HBox m_box; 2. Gestion des évènements window.add(m_box); Gtk::Label m_label('Cliquer pour quitter'); 3. Présentation des widgets Gtk::Button m_button('Quitter'); m_box.pack_start(m_label); m_box.pack_start(m_button);
m_button.signal_clicked().connect(sigc::ptr_fun(&on_butto n_clicked)); m_label.show(); m_button.show(); }
void maFenetre::on_button_clicked() { ... } 33 34 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Gestion des évènements La boucle d'évènements
Gtkmm implémente une boucle de gestion des évènements
Correspond au thread de l'interface Dans la classe Gtk::Main Lancée par Gtk::Main::run()
1. La boucle d'évènements int main(int, char **) int main(int argc, char *argv[]) 2. Les évènements d'affichage { { 3. Surcharger les handlers Gtk::Main app(); Gtk::Main kit(argc, argv); app.run(); Gtk::Window window; 4. Connexion des signaux return 0; 5. Activer les signaux X masqués } return Gtk::Main::run(window); }
35 36 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
La boucle d'évènements La boucle d'évènements
Exemple d'implémentation de la boucle d'évènements Les évènements sont traités au travers des notions de :
signal : un objet peut « émettre » un évènement décrit par un signal
while( program == running ) { action d'un utilisateur ( e.g. souris ou keyboard) while(not event_table.empty ()) { const Event &e = event_table.pop(); envoi programmé ( e.g. timer) switch ( e.type ()) { callback (ou handler ) : un objet peut être déclenché par des case Event::BUTTON_CLICKED : //Action à réaliser évènements, le callback est une fonction indique comment ... réagir ! case Event::NEED_REDRAW : ... default : Connexion } : le programmeur associe un signal à un } callback
37 38 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
La boucle d'évènement La boucle d'évènements
Table de connexion (pour se faire une vague idée du fonctionnement) Main Loop Events
While(events pending) Objet Évènement Action (callback)
Application Cacher exit() Callback Button1 Pressed fonction1() Expose events Re-Painting Button1 Released fonction2() invalidated regions Lookup callback for event Button2 Pressed fonction3() exit(0)
Button2 Pressed fonction4()
...
Hacking GTK+, -Muthiah A, Octave-Gtk+ team 39 40 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
La boucle d'évènements : 2 piles Gestion des évènements d'affichage
Une pile d’évènements (FIFO) : entasse et se dépile En fonction de ce qui se passe dans l'IHM, Gtkmm au fur et à mesure des demandes de l’utilisateur ou du détermine quels sont les zones à afficher programme Ajout dans une queue de zones à afficher Les signaux créent de nouveaux évènements, Chaque zone correspond à un widget Les callbacks les consomment Lors du traitement d'une zone à afficher Gtkmm fait Une pile d'évènements d'affichage ( expose appel à la fonction on_expose_event de la classe events ) Gtk::Widget Retient les zones de l'écran à rafraichir, En surchargeant la fonction on_expose_event on peut Gestion intelligente : évite des doublons, mutualisation des ajouter ou redéfinir l'affichage d'un widget régions !
Gtkmm assure la distribution des évènements
41 42 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Gestion des évènements d'affichage Gestion des évènements
bool ZoneDessin::on_expose_event(GdkEventExpose* event) { Glib::RefPtr
Gdk::Color bleu("blue"); get_default_colormap()->alloc_color( bleu ); Gdk::Color rouge("red"); get_default_colormap()->alloc_color( rouge );
gc->set_foreground(bleu); get_window()->set_background(rouge); 1. La boucle d'évènements get_window()->clear(); 2. Les évènements d'affichage get_window()->clear(); get_window()->draw_line(gc, 1, 1, 100, 100); 3. Connecter des évènements get_window()->draw_layout(gc, 40, 40, 1. Surcharger les handlers create_pango_layout("Bonjour")); 2. Connexion des signaux return true; } 4. Activer les signaux X masqués
43 44 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Connexion d'un évènement Surcharger les handlers
La connexion des évènements consiste à faire des ajouts Les widgets disposent déjà de handlers prédéfinis et dans la « table des connexions » connectés par défaut
Deux méthodes Fonctions identifiées par le préfixe on_ Surcharger les handlers Les fonctions sont virtual protected Établir des connexions Chaque handler est associé a un évènement du widget Exemples Gtk::Button : virtual void on_pressed () virtual void on_released () virtual void on_clicked () virtual void on_enter () virtual void on_leave () virtual void on_ activate ()
Il faut surchargées ces fonctions pour implémenter l'action désirée Nécessite de construire une classe spécifique pour chaque bouton 45 46 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Glib::SignalProxy0< void > signal_pressed () Glib::SignalProxy0< void > signal_released () Surcharger les handlers Les signaux Glib::SignalProxy0< void > signal_clicked () Glib::SignalProxy0< void > signal_enter () Glib::SignalProxy0< void > signal_leave () on_clicked() est appelé suite à un évènement X Les signaux Glib::SignalProxy0< void > signal_activate ()
#include
Les signaux et les callbacks Rappel sur les pointeurs de fonctions
Connexions des signaux (sans paramètres) Un pointeur de fonction
Rappel sur les pointeurs de fonctions Les signaux et les callbacks
using namespace std; Utilisation dans les // comparison, not case sensitive. Connexions des signaux (sans paramètres) bool compare_nocase (string first, string second) librairies standards { unsigned int i=0;
Les signaux et les callbacks Les signaux et les callbacks
La fonction connect() prend en paramètre un slot Connexions des signaux (sans paramètres) slot : représentation interne d'un pointeur de fonction
Fonction avec un paramètre de type double , et qui retourne un booléen Exemple
La fonction construit un slot à partir sigc::ptr_fun void on_button_clicked() { d'une fonction std::cout << "Hello World" << std::endl; On donne simplement un pointeur de fonction ( sans } parenthèses ! ) main() { Exemple : void foo( int ) Gtk::Button b("Hello World"); { } b.signal_clicked() .connect( sigc::ptr_fun( &on_button_clicked ) ); } sigc::slot< void, int > sl = sigc::ptr_fun(& foo );
53 54 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Connexion à une méthode Connexion à une méthode
sigc::ptr_fun( &handler ) : sert uniquement à connecter une fonction globale
sigc::mem_fun( objet , &handler ) : sert à connecter une void on_button_clicked();
méthode d'une classe pour un objet particulier class some_class { void on_button_clicked(); Utilisation identique : };
some_class some_object; void MaClasse::action() { main() { std::cout << "Hello World" << std::endl; Gtk::Button b; } b.signal_clicked().connect( sigc::ptr_fun(&on_button_clicked) ); b.signal_clicked().connect( sigc::mem_fun(some_object, void main() { &some_class::on_button_clicked) ); MaClasse obj , obj2; } Gtk::Button b("Hello World"); b.signal_clicked().connect( sigc::mem_fun( obj ,&MaClasse::action ) ); }
55 56 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Connexion des signaux aux callbacks Exemple de connexion
cf. Exemple buttonExample2.cpp Les détails techniques permettent de bien comprendre int main(int argc, char *argv[]) ce qui se passent mais peuvent être oublié dans la #include
button.show(); void myButton::clicked()
{ Gtk::Main::run(win); printf("Click!\n"); return 0; } 57 }; 58 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Exemple d'appel à un signal Signaux/callbacks avec paramètres
Certains signaux retournent valeurs ou ont des class myButton : public int main(int argc, char *argv[]) paramètres Gtk::Button { { public: Gtk::Main kit(argc, argv); Les handlers doivent les gérer myButton(){}; virtual ~myButton(){}; Gtk::Window win; La fonction exige la correspondance entre win.set_title("buttonExample 3"); connect() public: win.set_border_width(10); les profils de fonctions ( type safety à la compilation) void on_button_enter(); protected: myButton button;
Signaux/callbacks avec paramètres Signaux/callbacks avec paramètres
La fonction connect() exige la correspondance entre La fonction connect() exige la correspondance entre les profils de fonction les profils de fonction
Exemple Exemple signal_focus() .connect( ptr_fun( &ma_fonction ) ) signal_focus() .connect( ptr_fun( &ma_fonction ) )
Glib::SignalProxy 1
bool ma_fonction(Gtk::DirectionType direction); bool ma_fonction(); Les profils de fonction ne correspondent pas ! ptr_fun( &ma_fonction ) : slot< bool, Gtk::DirectionType > ptr_fun( &ma_fonction ) : slot< bool >
63 64 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Signaux/callbacks avec paramètres Signaux/callbacks avec paramètres
De même avec plusieurs paramètres (maximum 7) Pour forcer la correspondance entre profils, il faut
exemple de signal Gtk::editable parfois utiliser des fonctions de binding
sigc::bind : ajouter des paramètres au handler sigc::hide : masquer des paramètres du handler Glib::SignalProxy 3
65 66 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Signaux/callbacks avec paramètres Signaux/callbacks avec paramètres
Exemple d'utilisation de la fonction sigc::bind() Exemple d'utilisation de la fonction hide_return()
fonction : virtual void mon_handler(Glib::ustring data); Il faut que le type de retour de la fonction corresponde On veut la déclencher par un clic de bouton : également Glib::SignalProxy0< void > signal_clicked() handler : bool mon_handler(); signal : Glib::SignalProxy0< void > signal_clicked() Connexion à réaliser m_button.signal_clicked() .connect( sigc::bind
cf. exemple 4 : cf. exemple 4 : buttonExample_bind 67 buttonExample_bind 68 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Déconnection d'un signal Avantages et inconvénients
Pour déconnecter un signal, il suffit de faire appel à la Surcharge des handlers fonction disconnect() d'une connexion Avantage : facile et rapide Nécessite d'avoir conserver une trace de la connexion quelque Inconvénients :
part ! nécessite de surcharger la classe de base pour chaque nouveau comportement Les signaux peuvent être connectés et déconnectés solution nécessitant une forte dépendance entre la classe de l'objet dynamiquement appelant et celle de l'objet appelé
sigc::connection connexion = Connexion de signaux button_test.signal_clicked().connect ( sigc::ptr_fun( &test_connection ) Avantages : ); générique
(...) forte séparation appelant/appelé possible connexion.disconnect(); Inconvénients : les binds de functors
cf. exemple buttonExample_dynamicdisconnection 69 peut nécessiter un peu plus de travail de réflexion préalable ! 70 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Les signaux et les callbacks Gestion des évènements
Résumé
Chaque Widget est associé à des évènements un évènement
une fonction signal_XXX() : qui servir à connecter des actions aux évènements une fonction on_XXX( params ) : qui peut être surchargée Utilisation de la fonction connect() 1. La boucle d'évènements signal_XXX() .connect( mem_fun( object, &Class::function ) ) 2. Les évènements d'affichage Les fonctions de binding ( sigc::bind()) servent à modifier les 3. Connecter des évènements paramètres de la fonction à appeler pour correspondre au profil du signal ! 1. Surcharger les handlers 2. Connexion des signaux La fonction appelée doit récupérer tous les paramètres du signal 4. Activer les signaux X masqués Il est possible de connecter et déconnecter dynamiquement les signaux 71 72 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Les signaux X usuels Les signaux X usuels
Dans la classe Gtk::Widget : tous les widgets peuvent, Les signaux d'affichage
en principe, les utiliser Glib::SignalProxy1< bool, GdkEventExpose* > signal_expose_event () Glib::SignalProxy1< bool, GdkEventExpose* > signal_configure_event () Les signaux des évènements X (repérés par _event ) Glib::SignalProxy0
Glib::SignalProxy1
Glib::SignalProxy1
73 74 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Activation des signaux X usuels Activation des signaux X usuels
Utilisation par défaut des signaux X Exemple : activation des clics de souris sur un Dans un certain nombre de widget, les signaux X sont déjà Gtk:DrawingArea utilisés pour les signaux propres à l'objet Pour les autres, ils ne sont pas écouté par Gtk
Récupérer les signaux X d'un widget Gtk::DrawingArea widg; Dans le premier cas, on peut utiliser un EventBox , et widg. add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK); indiquer les signaux à écouter widg. signal_button_press_event() .connect( ... ); Dans le second, il suffit (mais nécessaire) d'indiquer les widg. signal_button_release_event() .connect( ... ); signaux à écouter
75 76 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Exemple : rendre un label cliquable La boucle d'évènements
bool on_button_clicked(GdkEventButton*) Petit exercice de compréhension { std::cout << "fonction clicked\n"; On propose d'afficher l'évolution d'un traitement en modifiant }; le label d'un bouton ainsi Gtk::EventBox m_EventBox ; fenetre.add(m_EventBox); Que va-t-il se passer en pratique ? Gtk::Label m_Label("Mon label") ; m_EventBox .add( m_Label ); m_Label.set_size_request(110, 20); void go() { long i=LONG_MIN; //Préparation pour l'action (a faire avant l'affichage pour éviter long max= LONG_MAX; les erreurs) while( i < max ) { m_EventBox .set_events(Gdk::BUTTON_PRESS_MASK); double result = cos((double)i*PI/180); button->set_label( Glib::ustring::compose("done %1%%", (...) (double)i/(double)max) ); i++; //Connexion : sur l'Eventbox ! } m_EventBox .signal_button_press_event() .connect( sigc::ptr_fun( &on_bu } tton_clicked ) );
cf. exemple 5 : Almostlong.cpp 77 78 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Plan de cours Présentation des widgets
1. Vision d'ensemble Objectif : 2. Gestion des évènements Faire une revue rapide, non-exhaustive des widgets usuels S'appuyer fortement sur la documentation 3. Présentation des widgets Pour que je ne recopie pas ce qui y est déjà ! ( principe n°1 de l'informaticien : ne pas refaire ce qui fonctionne bien ! )
Pour que vous trouviez facilement les informations dont vous avez besoin Donner quelques exemples pratiques exemplaires de l'utilisation de Widgets
80 81 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Présentation des widgets La classe Widget
Fonction liée à la géométrie du Widget
Déterminer la taille d'un widget
void set_size_request (int width=-1, int height=-1)
Les requêtes de taille ne sont pas nécessairement satisfaites ! Connaître la taille d'un widget
get_width() et get_height() 1. La classe Widget Allocation get_allocation () const 2. La hiérarchie des Widgets Allocation : permet de connaître la taille et la position du 3. Présentation de qqs des widgets standard widget (alloué par le windows manager) 4. Autres éléments d'une interface
82 83 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
La classe Widget La classe Widget
Modifier le style d'un Widget Les fonctions d'affichage style = couleurs, polices par défaut, pixmap de fond, ... void show(), void show_all(), void show_now() fonctions modify_...() show() : Flags a widget to be displayed, Les widgets qui ne sont pas flaggés ne seront pas affichés !! annulé avec la fonction unset_...() show_all() : Recursively shows a widget, and any child widgets Modifier la couleur de fond d'un Widget (if the widget is a container), void modify_bg (StateType state, const Gdk::Color& color) show_now() : Shows a widget. -> Rentre dans la boucle Gtk::StateType = {STATE_NORMAL, STATE_ACTIVE, principale et attend que le widget soit effectivement affiché. STATE_PRELIGHT, STATE_SELECTED, STATE_INSENSITIVE} Attention à son utilisation (!) color = Gdk::Color('yellow'); (Voir /usr/share/X11/rgb.txt) void queue_draw() et void queue_draw_area() La modification passe par l'appel d'un évènement X. Le Invalide une région de l'interface
Widget doit pouvoir le recevoir pour que la modification Dans la boucle de traitement , une fois les évènements traités soit effective ! les régions invalidées reçoivent des évènements expose_event .
84 85 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Hiérarchie des Widgets Hiérarchie des Widgets
86 87 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Widget standard Fenêtre ( Gtk::Window)
La classe est le widget représentant une fenêtre Standard Widgets Layout Widgets MVC Widgets Window dans l’environnement graphique. Button Window TreeView Label Container TextView C'est la seule classe représentant un « vrai » objet X Entry Box ListView possède les fonctions en relation avec le window manager , Radio Table Check Scrolled Window comme par exemple iconifi er la fenêtre, l’enrouler, etc. Menubar Menu On ne peut lancer qu'un Gtk::Window avec run() Scrollbar Drawing Widgets Misc Widgets int main ( int argc , char ** argv ) { Progressbar Pane Gtk::Main app(argc , argv); Ruler Drawing Area Fixed Gtk::Window w; Scale Window Separators Dialogs Curve app.run(w); Tearoff menu items } Tooltips Preview Notebook
Hacking GTK+, -Muthiah A, Octave-Gtk+ team 88 89 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Fenêtre ( Gtk::Window) Boutons
On peut y inclure 1 autre Widget (mais pas 2!) Gtk::Button ( doc ) Gtk::Button button; signal_clicked() window. add (button); Gtk::ToggleButton ( doc ) Qqs membres spécifiques Bouton qui peut conserver son état toggle() to switch the state void set_title(const Glib::ustring& title) void set_active(bool =true) void set_icon (const Glib::RefPtr
90 91 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Les mnémonics ComboBox
Mnémonic : permet à l'utilisateur d'une interface de Liste de choix déroulante déclencher rapidement le bouton par une combinaison de touche
Exemple: Alt+B m_Combo.append_text('...') : ajoute un item signal_changed() : signale la modification d'un choix (Sans arguments) Dans le constructeur : Glib::ustring get_active_text() : récupère le Button('mon _Button' , true ) texte de l'item affiché Fonctions add_label et add_mnemonic_label
92 93 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
ComboBox : exemple Entry
ExampleWindow::ExampleWindow() Entrée textuelle sur 1 ligne { m_Combo.append_text("something"); Propriétés : m_Combo.append_text("something else"); m_Combo.append_text("something or other"); visible (= false : mode password) add(m_Combo); editable max_length //Connect signal handler: m_Combo.signal_changed().connect(sigc::mem_fun(*this, Gestion du contenu textuel : &ExampleWindow::on_combo_changed) ); set_text(Glib::ustring t) show_all_children(); Glib::ustring get_text() } Signaux : void ExampleWindow::on_combo_changed() { signal_changed(), signal_insert_text(), Glib::ustring text = m_Combo.get_active_text(); signal_delete_text() if(!(text.empty())) std::cout << "Combo changed: " << text << std::endl; signal_insert_at_cursor() (retourne la chaîne insérée) } signal_selection_received(), signal_selection_get() 94 95 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Label Label
Le Label est un composant simple qui représente une Le Label est un composant simple qui représente une chaîne de caractères dans une zone graphique. chaîne de caractères dans une zone graphique.
Label (const Glib::ustring& label, AlignmentEnum xalign, int main( int argc , char ** argv ) { AlignmentEnum yalign=ALIGN_CENTER, bool mnemonic=false) Gtk::Main app(argc , argv); Gtk::Window w ; Gtk::Label label ; label. set_markup("hello world !"); Label( 'Bonjour !' ); w.add( label ); Label( Glib::ustring('Banzaï') ); app.run( w ); }
96 97 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Label Solution : les EventBox
C'est un élément qui ne permet pas de recevoir des Exemple : modification de la couleur de fond d'un label
évènements X Gtk::EventBox m_eventbox; m_eventbox.add(m_label); Formellement, il ne s'agit pas d'une fenêtre X m_eventbox.modify_bg(Gtk::STATE_NORMAL, Gdk::Color('red') ); exemple ( label_Color.cpp ) : m_eventbox.show(); m_label.show(); m_label.modify_bg( Gtk::STATE_NORMAL, Gdk::Color('red') )
Modifie la couleur du fond d'un widget Uniquement pour les « non-bin » Fait appel à un évènement X pour modifier cette propriété, mais Généralement utilisé sur les widget Misc l'évènement n'est pas pris en compte : le label reste gris !! Label , Image et Arrow
98 99 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Autres widget « non-bin » Solution : les EventBox
Gtk::Pixmap Gtk::Alignment Exemple: récupérer les évènements X d'un Label Gtk::RadioButton Gtk::Arrow set_events : Définit les types d'évènement X qui doivent être considérés Gtk::Range Gtk::Box signal_button_press_event() : correspond à un signal X de pression Gtk::ScrolledWindow Gtk::CheckButton de bouton Gtk::Separator Gtk::Fixed Nom de fonction préfixée par ' _event ' Gtk::Table Gtk::Image Gtk::Toolbar Gtk::Item Gtk::AspectFrame Gtk::Label m_label("Click here"); Gtk::Frame add(m_eventbox); Gtk::MenuItem m_eventbox.add(m_Label); Gtk::VBox Gtk::Notebook m_label.set_size_request(110, 20); Gtk::HBox Gtk::Paned m_eventbox.set_events(Gdk::BUTTON_PRESS_MASK); Gtk::VSeparator m_eventbox.signal_button_press_event(). connect( sigc::mem_f Gtk::HSeparator un(*this, &ExampleWindow::on_eventbox_button_press) );
100 101 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Les containers / conteneurs Les containers / conteneurs
Deux types de conteneurs Deux types de conteneurs Parent Les conteneurs à un unique widget Les conteneurs à un unique widget
Frame En tant que widget, il est positionné dans un Conteneur simple Dialog widget parent (sauf Gtk::Window )
Alignement Contient un autre widget : il est ajouté avec une Window fonction add EventBox Les conteneurs multiples
Les conteneurs multiples, dont En tant que widget, il est positionné dans un Parent HBox : une liste dynamique d'espaces horizontaux widget parent VBox : une liste dynamique d'espaces verticaux Contient un ou plusieurs autres widgets Conteneur Table : Grille de Widgets Les fonctions d'ajout dépendent des conteneurs multiple NoteBook : un widget à onglets Menus/Toolbar
Fixed : un conteneur à placement libre 102 103 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Les containers / conteneurs Les containers / conteneurs
Les containers permettent de structurer une interface Représentation des zones sous la formes d'arbres graphique en « zones » Les zones sont disjointes Les séparations sont uniquement verticales et horizontales Exception Gtk::Fixed : container de placement libre des widgets
Conteneurs multiples
Conteneurs simples
104 105 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Frame Alignement
Élément décoratif Alignement d'un widget dans un conteneur
Contient le widget à aligner
Propriétés Constructeur : le label Alignment (AlignmentEnum xalign, AlignmentEnum yalign=Gtk::ALIGN_CENTER, float xscale=1.0, float Gtk::Window m_window; Gtk::Frame m_Frame; yscale=1.0) Gtk::DrawingArea m_DrawingArea;
m_Frame.set_label('Frame'); Gtk::Window m_window; Gtk::Alignment m_Alignment(Gtk::ALIGN_RIGHT, // Ajout d'un widget fils Gtk::ALIGN_CENTER, 0.0, 0.0); m_Frame.add (m_DrawingArea); Gtk::Button m_Button(''Close'');
// Ajout du cadre à la fenêtre m_window.add( m_Alignment ); m_window.add( m_Frame ); m_Alignment.add (m_Button ); 106 107 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Containers multiples Les Boxes (HBox ou VBox)
Les conteneurs multiples, dont Fonctions d'addition de widget HBox : une liste dynamique d'espaces horizontaux void pack_start(Gtk::Widget& w); ou void VBox : une liste dynamique d'espaces verticaux add(Gtk::Widget& w); Table : Grille de Widgets void pack_end(Gtk::Widget& w); NoteBook : un widget à onglets Fonction de suppression de widget Menus/Toolbar void remove(Gtk::Widget& w); Fixed Fonction de réordonnancement : void reorder_child(Gtk::Widget& child, int pos)
108 109 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Les Boxes (HBox ou VBox) Les Boxes (HBox ou VBox)
void pack_start (Widget& child, PackOptions options=PACK_EXPAND_WIDGET, guint padding=0) Exemple : pack_example.cpp void pack_start (Widget& child, bool expand, bool fill, guint padding=0)
Détails d'une fonction pack PackOptions
PACK_SHRINK : Space is contracted to the child widget size. Gtk::VBox m_box; (expand = false, peu importe fill ) Gtk::Label m_label1("1"), m_label2("2"), m_label3("3");
PACK_EXPAND_PADDING : Space is expanded, with extra space bool expand=true; //Indique si le box doit s'étirer avec le filled with padding. ( expand = true, fill =false ) parent bool fill=true; //Indique si les widgets du box doivent PACK_EXPAND_WIDGET : Space is expanded, with extra space s'étirer avec le box ! (uniquement si expanding = true) filled by increasing the child widget size. ( expand = true, fill int padding=10; //minimum d'espace entre les widgets du box =true ) m_box.pack_start (m_label1 , expand, fill, padding); Padding : espace fixe autour des widgets m_box.pack_start (m_label2 , true, fill, padding); m_box.pack_start (m_label3 , expand, fill, padding); 110 111 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Les Boxes (HBox ou VBox) Fixed : un container particulier !
Permet de positionner les widget où l'on veut, avec les tailles que l'on veut Sort des contraintes VBox ou Hbox,
Fonctions void move(Widget& w, int x, int y) void put(Widget& w, int x, int y) void remove(Widget &w)
L'utilisation de ce container est peu recommandée dans les interfaces classiques problèmes d'overlapping
112 113 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Widget standard Présentation des widgets
Standard Widgets Layout Widgets MVC Widgets
Button Window TreeView Label Container TextView Entry Box ListView Radio Table Check Scrolled Window Menubar Menu Scrollbar Drawing Widgets Misc Widgets 1. La classe Widget Progressbar Pane Ruler Drawing Area 2. La hiérarchie des Widgets Fixed Scale Window Separators 3. Présentation de qqs des widgets standard Dialogs Curve Tearoff menu items 4. Autres éléments d'une interface Tooltips Preview Notebook
Hacking GTK+, -Muthiah A, Octave-Gtk+ team 114 115 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Autres éléments d'une interface Les boîtes de dialogue
Autres éléments permettant de construire une interface Boîte de dialogue : Affiche des messages courts ou de Les boîtes de dialogue récupérer des informations courtes Les menus Classe Gtk::Dialog La barre d'outils Fenêtre composée verticalement avec des Gtk::Label et des ou encore ( cf. documentation) Gtk::Entry Fonctions de pack sur le VBox récupéré par : Vbox* get_vbox() La barre d'état Associée à une action de retour Les documents récents Des boutons ( Button* add_button (const Glib::ustring& Le clipboard button_text, int response_id) ) Les impressions ou d'autres actions (cf. add_action_widget(...) ) Est exécutée avec la fonction int run() retourne uniquement un entier correspondant à l'action de l'utilisateur 116 117 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Les boîtes de dialogue Les boîtes de dialogue
MessageDialog Permet d'afficher des messages à l'utilisateur
MessageDialog (Gtk::Window& parent, const Glib::ustring & message, bool use_markup = false , MessageType type = MESSAGE_INFO , ButtonsType Gtk::MessageDialog dialog(*this, "This is a QUESTION MessageDialog", false /* buttons = BUTTONS_OK , bool modal = false ) use_markup */, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL); dialog.set_secondary_text( "And this is the secondary text that explains things."); int result = dialog .run() ; //Handle the response: switch(result) { BUTTONS_NONE case(Gtk::RESPONSE_OK): { MESSAGE_INFO std::cout << "OK clicked." << std::endl; BUTTONS_OK break; MESSAGE_WARNING } BUTTONS_CLOSE case(Gtk::RESPONSE_CANCEL): { MESSAGE_QUESTION std::cout << "Cancel clicked." << std::endl; BUTTONS_CANCEL break; MESSAGE_ERROR } BUTTONS_YES_NO default: { MESSAGE_OTHER std::cout << "Unexpected button clicked." << std::endl; BUTTONS_OK_CANCEL break; } 118 } 119 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Autres boîtes de dialogue Les menus et barre d'outils
FileChooserDialog Les menus et les icônes d'une barre d'outils sont
ColorSelectionDialog associés à des Gtk::Action
FontSelectionDialog Pour créer un menu, il faut créer un groupe d'actions Gtk::ActionGroup AboutDialog
Le groupe d'actions est géré par le UIManager Disposition dans le menu Affichage dans la barre d'outils
120 121 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Les menus et barre d'outils Les menus et barre d'outils
Création d'un groupe d'actions Création d'un groupe d'actions Utilisation de la fonction create() Utilisation de la fonction create()
Glib::RefPtr
m_refActionGroup-> add ( Gtk::Action::create("MenuFile", "_File") ); m_refActionGroup-> add ( Gtk::Action::create("MenuFile", "_File") ); m_refActionGroup-> add ( Gtk::Action::create("ExportData", "Export Data"), sigc::mem_fun(*this, &ExampleWindow::on_action_file_open) ); Ajoute une action identifiée par « MenuFile » et qui affiche le texte « File » Création d'une « vraie » action
C'est un menu racine : contient des sous-menus et n'est pas Associe l'action à un handler : action à réaliser lors du clic ! associé à une action Mnémonic : « _ » pour les touches d'accès rapide
122 123 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Les menus et barre d'outils Les menus et barre d'outils
Création d'un groupe d'actions UIManager Utilisation de la fonction create() insert_action_group : associe les actions à gérer add_accel_group : ajout de la gestion, par la fenêtre, des Glib::RefPtr
Gtk::Stock : internationalisation dans Gtkmm
124 125 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010
Les menus et barre d'outils Les menus et barre d'outils
UIManager Réalisation du menu et de la barre d'outil
Glib::ustring ui_info = La fenêtre doit pouvoir contenir plusieurs widgets => "
Bibliographie
Cours de C++ et Gtk-- , Quesnel Gauthier, 2006
http://www-lil.univ-littoral.fr/~quesnel/cplusplus.php
Programming-with-gtkmm , Murray Cumming, Bernhard Rieder, Jonathon Jongsma, Jason M’Sadoques, Ole Laursen, Gene Ruebsamen, Cedric Gustin, Marko Anastasov, and Alan Ott , 379 pages, 2006
http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/pdf/programming-with-gtkmm.pdf
Fondations of Gtk+ development , Andrew Krause, Apress, 629 pages, 2007.
www.gtkbook.com/
Sites internet
www.gtk.org www.gtkmm.org
Pointeur sur les ressources de ce cours http://www.irisa.fr/dream/Pages_Pros/Thomas.Guyet/enseignements/OCI/
128 Guyet Thomas - Cours OCI - M2 GL - IFSIC - 2010