Introduction à GTK en C++ - Gimp Tool Kit for C++ - LISIC

publicité
Introduction à GTK en C++
Gimp Tool Kit for C++
Gauthier Quesnel et Eric Ramat
{quesnel,eramat}@users.sourceforge.fr
Institut National de la Recherche Agronomique
Université du Littoral - Côte d’Opale
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
1 / 57
1
gtkmm
La philosophie
La boucle événementielle
Les widgets
Les événements
2
glibmm , glade et libglademm
glibmm
glade
libglademm
3
Outils
pkg_config
Makefile
Les liens
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
2 / 57
gtkmm qu’est ce ?
gtkmm anciennement nommée gtk– est une API de programmation
d’interfaces graphiques.
C’est un wrapper sur gtk+ : the Gimp ToolKit.
Disponible sur la plupart des plateformes : Unix, Windows.
Cette bibliothèque se base sur les bibliothèques :
I
I
I
gdkmm le lien entre X-Window et gtkmm ou Win 32 et gtkmm .
glibmm les fonctions de base, les outils de portabilité.
sigc++ la gestion des événements via les signaux.
Quelques exemples : Inkspace, K-3D, . . .
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
3 / 57
Plan
1
gtkmm
La philosophie
La boucle événementielle
Les widgets
Les événements
2
glibmm , glade et libglademm
glibmm
glade
libglademm
3
Outils
pkg_config
Makefile
Les liens
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
4 / 57
Histoire
gtk+ est un toolkit développé pour Gimp 1.0 et repris par le projet
GNU comme API de base pour le développement du projet Gnome.
La philosophie de développement de gtkmm se base sur celle de
gtk+ : écrire le moins de code possible pour définir des interfaces
graphiques simples d’utilisation.
Le nom des fonctions membres sont les mêmes que celle de gtk+.
Il existe un très grand nombre de « wrappers » pour gtk+. Les plus
connus sont :
I
I
gtkmm , java-gnome, gtk2-perl, PyGTK
GtkAda, GTKKit
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
5 / 57
Les événements : philosophie signal / slot
Les événements sont gérés par la bibliothèques sigc++ sous formes
d’appels de fonctions.
Des paramètres peuvent être fournis à ces fonctions pour transmettre
des information sur l’événement.
Les événements dans les applications gtkmm se manipulent de deux
manières :
I
I
Par connexion d’un événement, signal, sur une fonction de classe,
d’objet ou une fonction globale, slot.
Par polymorphisme, via la surcharge des fonctions virtuelles
représentant les événements d’une classe.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
6 / 57
Plan
1
gtkmm
La philosophie
La boucle événementielle
Les widgets
Les événements
2
glibmm , glade et libglademm
glibmm
glade
libglademm
3
Outils
pkg_config
Makefile
Les liens
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
7 / 57
La boucle événementielle
Un programme graphique utilise une boucle événementielle : tant que
l’utilisateur ne fait pas d’action sur l’interface, celle-ci ne réagit pas.
Sur les systèmes X-Window, il existe une pile d’événements qui
s’entassent et se dépilent au fur et à mesure des demandes de
l’utilisateur ou du programme.
Les événements sont les mouvements et clic sur la souris, l’appui sur
une touche etc.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
8 / 57
La boucle événementielle
Exemple d’implémentation simplifiée
1
2
3
4
5
6
7
8
9
10
11
while ( program == running ) {
while ( not event_table . empty ()) {
const Event & e = event_table . pop ();
switch ( e . type ()) {
case Event :: BUTT ON_CLICK ED :
...
case Event :: NEED_REDRAW :
...
default :
}
}
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
9 / 57
La boucle événementielle
Exemple d’implémentation simplifiée
1
2
3
4
5
6
7
8
9
10
11
while ( program == running ) {
while ( not event_table . empty ()) {
const Event & e = event_table . pop ();
switch ( e . type ()) {
case Event :: BUTT ON_CLICK ED :
...
case Event :: NEED_REDRAW :
...
default :
}
}
Attention
Il ne faut surtout pas rester trop longtemps dans une réponse sinon, les
événements s’empileront dans la pile mais ne seront pas gérés au bon
moment.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
9 / 57
La boucle événementielle, les problèmes
1
2
3
4
5
6
7
8
9
10
11
12
while ( program == running ) {
while ( not event_table . empty () == false ) {
const Event & e = event_table . pop ();
if ( e . type () == Event :: BUTTON_ CLICKED ) {
for ( int i = 0; i < 100; ++ i ) {
simulation . make_step ();
image . update_screen ();
drawingarea . need_redraw (); // add NEED_REDRAW event
}
// to the event_table .
} else if ( e . type () == Event :: NEED_REDRAW ) {
drawingarea . copy ( image );
...
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
10 / 57
La boucle événementielle, les problèmes
1
2
3
4
5
6
7
8
9
10
11
12
while ( program == running ) {
while ( not event_table . empty () == false ) {
const Event & e = event_table . pop ();
if ( e . type () == Event :: BUTTON_ CLICKED ) {
for ( int i = 0; i < 100; ++ i ) {
simulation . make_step ();
image . update_screen ();
drawingarea . need_redraw (); // add NEED_REDRAW event
}
// to the event_table .
} else if ( e . type () == Event :: NEED_REDRAW ) {
drawingarea . copy ( image );
...
Le programme ne fonctionnera pas
La pile d’événements contiendra 100 appels de modification de l’affichage,
NEED_REDRAW, mais n’en fera aucun puisque vous ne rendait pas la main à
la boucle événementielle.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
10 / 57
Correction du problème
Le problème précédent peut se résoudre : timer ou un thread.
1
2
3
4
5
6
7
8
9
10
11
bool horloge () {
static int i = 0;
i = i + 1
if ( i != 100) {
simulation . make_step ();
image . update_screen ();
drawingarea . need_redraw ();
return true ; // the timer is not killed .
}
return false ; // the time is killed .
}
12
13
14
15
16
int main () {
// function horloge call every 100 ms
timer = c r e a t e _ f o n c t i o n _ t i m e r (& horloge , 100);
}
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
11 / 57
Autre exemple
On peut forcer la lecture des événements :
1
2
3
4
o u v r e _ d i a l o g u e _ a v e c _ b a r r e _ d e _ p r o g r e s s i o n ();
for ( int i = 0; i < 100; ++ i ) {
f a i t _ u n _ g r o s _ c a l c u l ();
m a j _ b a r r e _ p r o g r e s s i o n ();
5
6
7
8
9
10
while ( Gtk :: Main :: events_pe nding ()) { // on mange les événements
Gtk :: Main :: iteration ( false );
// restants dans la pile
}
}
ferme _dialogu e
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
12 / 57
Structure du X Window System
X est une application en fonctionnement client / serveur.
I
I
serveur : gère l’écran, le clavier et la souris d’une machine. Reçoit et
émet des requêtes d’affichage, d’entrée.
client : une application graphique se connectant au serveur X et
utilisant le protocole X en utilisant la Xlib.
Les communications entre les clients et le serveur utilisent une
« socket »permettant ainsi de déporter l’affichage.
Les communications locales passes par un pipe, ie. aucune perte de
vitesse due au socket.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
13 / 57
Structure du X Window System
toto@local: $ ssh -X vle.univ-littoral.fr
toto@vle: $ firefox &
Attention
Uniquement si le fichier /etc/ssh/sshd_config possède le paramètre
X11Forwarding à yes.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
14 / 57
X Window System et les threads
Le protocole X est un protocole asynchrone, cependant la
bibliothèque Xlib est synchrone :
I
I
Quand un programme demande de dessiner quelque chose au serveur, il
doit recevoir de la Xlib un message indiquant que tout c’est bien passé
avant de passer à autre chose.
L’utilisation de plusieurs threads dans un processus doit faire l’objet
d’une attention particulière afin de ne pas faire des demandes de dessin
simultané.
F
F
Pas propre : chaque thread protège son accès à Gtk/Gdk/Xlib par un
mutex.
Propre : un seul thread accède à X, les autres manipulent les données.
Attention
Étudier proprement votre interface graphique afin de limiter les protections
mutex.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
15 / 57
Plan
1
gtkmm
La philosophie
La boucle événementielle
Les widgets
Les événements
2
glibmm , glade et libglademm
glibmm
glade
libglademm
3
Outils
pkg_config
Makefile
Les liens
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
16 / 57
Introduction aux widgets
La version de Gtkmm utilisée en TP est la version 2.0, compatible
avec la version 2.2. mais incompatible avec la version courante, 2.4 /
2.6 / 2.8.
Les incompatibilités concernent principalement la bibliothèque sigc++ .
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
17 / 57
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
18 / 57
Fenêtre
La classe Window est le widget représentant une fenêtre dans
l’environnement graphique. Cette classe possède les fonctions en relation
avec le window manager, comme par exemple iconifier la fenêtre, l’enrouler
etc.
1
2
3
4
5
6
int main ( int argc , char ** argv )
{
Gtk :: Main app ( argc , argv );
Gtk :: Window w ;
app . run ( w );
}
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
19 / 57
Fenêtre
La classe Window est le widget représentant une fenêtre dans
l’environnement graphique. Cette classe possède les fonctions en relation
avec le window manager, comme par exemple iconifier la fenêtre, l’enrouler
etc.
1
2
3
4
5
6
int main ( int argc , char ** argv )
{
Gtk :: Main app ( argc , argv );
Gtk :: Window w ;
app . run ( w );
}
Attention
La fenêtre est un conteneur d’un widget
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
19 / 57
Label
Le Label est un composant simple qui représente une chaîne de caractères
dans une zone graphique.
1
2
int main ( int argc , char ** argv ) {
Gtk :: Main app ( argc , argv );
3
Gtk :: Window w ;
Gtk :: Label label ;
label . set_markup ( " <i > hello </ i > <u > world </ u > <b >! </ b > " );
4
5
6
7
w . add ( label );
app . run ( w );
8
9
10
}
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
20 / 57
Label
Le Label est un composant simple qui représente une chaîne de caractères
dans une zone graphique.
1
2
int main ( int argc , char ** argv ) {
Gtk :: Main app ( argc , argv );
3
Gtk :: Window w ;
Gtk :: Label label ;
label . set_markup ( " <i > hello </ i > <u > world </ u > <b >! </ b > " );
4
5
6
7
w . add ( label );
app . run ( w );
8
9
10
}
Example
À noter que ce widget peut accepter une syntaxe simplifiée du langage
HTML.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
20 / 57
Bouton
Le Button est très simple à gérer. Plusieurs possibilités existent comme la
création d’un bouton avec un label, une icône, un bouton fourni par la
bibliothèque.
1
2
int main ( int argc , char ** argv ) {
Gtk :: Main app ( argc , argv );
3
Gtk :: Window w ;
Gtk :: Button b ( " bonjour " );
4
5
6
w . add ( b );
app . run ( w );
7
8
9
}
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
21 / 57
Bouton
Le Button est très simple à gérer. Plusieurs possibilités existent comme la
création d’un bouton avec un label, une icône, un bouton fourni par la
bibliothèque.
1
2
int main ( int argc , char ** argv ) {
Gtk :: Main app ( argc , argv );
3
Gtk :: Window w ;
Gtk :: Button b ( " bonjour " );
4
5
6
w . add ( b );
app . run ( w );
7
8
9
}
Example
À noter que plusieurs constructeurs existent avec des icônes, textes,
images etc.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
21 / 57
Zone de textes
Le widget TextView fonctionne en modèle/vue/contrôleur. On retrouve
toutes les fonctions nécessaires comme la coloration syntaxique, la gestion
des paragraphes, l’alignement du texte.
1
2
3
Gtk :: TextView m_text ;
// Get a reference on the text .
Glib :: RefPtr < Gtk :: TextBuffer >& buffer = m_text - > get_buffer ();
4
5
6
// Put string " Hello World !"
buffer - > insert ( buffer - > end () , " Hello World ! " );
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
22 / 57
Zone de textes
Le widget TextView fonctionne en modèle/vue/contrôleur. On retrouve
toutes les fonctions nécessaires comme la coloration syntaxique, la gestion
des paragraphes, l’alignement du texte.
1
2
3
Gtk :: TextView m_text ;
// Get a reference on the text .
Glib :: RefPtr < Gtk :: TextBuffer >& buffer = m_text - > get_buffer ();
4
5
6
// Put string " Hello World !"
buffer - > insert ( buffer - > end () , " Hello World ! " );
Example
Un exemple d’implémentation d’un TextView se trouve dans le logiciel
gedit.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
22 / 57
Zone de dessin
La classe DrawingArea est un widget sans spécificité. Il est laissé libre aux
développeurs pour être hérité et amélioré. Les fonctions de dessins sont
disponibles en récupérant une référence sur le Gdk::Window et le Gdk::GC.
1
2
Gtk :: DrawingArea aire ;
int largeur , hauteur ;
3
4
5
6
7
8
// Récupère la zone de dessin du widget , de a taille
// de la fenêtre et d ’ un pinceau noir par défaut .
Glib :: RefPtr < Gdk :: Window > win = aire . get_window ();
win - > get_size ( largeur , hauteur );
Glib :: RefPtr < Gdk :: GC > gc = aire . get_style () - > get_black_gc ();
9
10
11
12
// Draw on the Gdk :: Window
win - > draw_line ( gc , 0 , 0 , largeur , hauteur );
win - > draw_line ( gc , 0 , hauteur , largeur , 0);
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
23 / 57
Les conteneurs
Deux types de conteneurs existent en gtk+ suivant la capacité qu’il
possède :
Conteneurs à un widget, héritent de Gtk::Bin
I
I
I
I
Frame : un rectangle avec un label.
Dialog : la boîte de dialogue minimale.
Alignement : placement aligné sur une bordure.
Window : la fenêtre.
Conteneurs multiple, héritent de Gtk::Container
I
I
I
I
VBox : une liste dynamiques d’espaces verticaux.
HBox : une liste dynamiques d’espaces horizontaux.
NoteBook : un widget à onglets.
Table : une tableau de taille dynamique.
Information
Il existe bien sûr d’autres conteneurs.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
24 / 57
Conteneurs : un exemple
1
2
3
4
5
6
7
8
int main ( int argc , char ** argv ) {
Gtk :: Main app ( argc , argv );
Gtk :: Window w ;
Gtk :: VBox vbox ;
Gtk :: HBox hbox ;
Gtk :: Button b1 ( " b1 " );
// create 3 buttons .
Gtk :: Button b2 ( " b2 " );
Gtk :: Button b3 ( " b3 " );
9
hbox . pack_start ( b1 , true , true );
// pack_start add widget
hbox . pack_start ( b2 , false , false ); // see Gtkmm documentation
vbox . pack_start ( b3 , true , true );
vbox . pack_start ( hbox , false , false );
10
11
12
13
14
w . add ( vbox );
w . show_all ();
w . set_title ( " Test d ’ un conteneur " );
app . run ( w );
15
16
17
18
19
}
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
25 / 57
Conteneurs : un exemple
Fig.: Résultat du programme conteneurs.cc
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
26 / 57
Plan
1
gtkmm
La philosophie
La boucle événementielle
Les widgets
Les événements
2
glibmm , glade et libglademm
glibmm
glade
libglademm
3
Outils
pkg_config
Makefile
Les liens
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
27 / 57
Gérer les événements
Pour rappel, il existe deux modes de gestions des événements :
I
I
héritage : surcharger la fonction de gestion de l’événement par votre
propre fonction. Les fonctions se nomment : on_[widget]_[event].
connexion : connecter le signal de l’événement à une fonction. Les
fonctions se nomment : signal_[event]
Deux exemples de la gestion d’un clic sur un bouton :
void on_button_clicked() { ...}
bouton.signal_clicked().connect(sigc::mem_fun(*this,
&Function));
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
28 / 57
Où trouver les noms ?
La source principale d’information :
http://www.gtkmm.org/gtkmm2/docs/reference/html/
Par exemple pour un bouton, les signaux à connecter sont :
Glib::SignalProxy0<void> signal_pressed();
Glib::SignalProxy0<void> signal_released();
Glib::SignalProxy0<void> signal_clicked();
Glib::SignalProxy0<void> signal_enter();
Glib::SignalProxy0<void> signal_leave();
Les fonctions à
virtual void
virtual void
virtual void
virtual void
virtual void
hériter sont :
on_pressed()
on_released()
on_clicked()
on_enter()
on_leave()
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
29 / 57
Connexion
Un premier exemple de connexion du clic sur le bouton de souris à une
fonction membre de la classe :
class Fenetre : public Gtk::Window
{
Gtk::Button button;
void cliquer() {
std::cout << "cliquer\n";
}
public:
Fenetre() : button("ok") {
button.signal_clicked().connect(sigc::mem_fun(*this, &Fenetre::cliquer));
}
}
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
30 / 57
Héritage
Si nous reprenons le même exemple du Button, nous pouvons définir une
classe MonBouton qui surcharge la fonction virtuelle du clic sur le bouton
de la souris.
class MonButton : public Gtk::Button {
public:
MonButton() : Gtk::Button("Ok")
virtual void on_clicked() { std::cout << Cliquer"; }
}
class Fenetre : public Gtk::Window {
MonButton button;
public:
Fenetre() { }
}
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
31 / 57
Les événements utiles
expose_event() : Elle a le même rôle que la fonction paint() du
java, elle est appelé par la pile événementielle pour réafficher le
contenu d’un widget.
configure_event() : Cette fonction est appelée lors de la
modification d’un composant : sa taille ou sa position.
key_press_event() : appelée lors de l’appuie sur une touche du
clavier.
Information
Pour insérer un demande de mise à jour de la zone graphique d’un dessin,
on appel la fonction queue_draw();
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
32 / 57
Plan
1
gtkmm
La philosophie
La boucle événementielle
Les widgets
Les événements
2
glibmm , glade et libglademm
glibmm
glade
libglademm
3
Outils
pkg_config
Makefile
Les liens
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
33 / 57
Quelques outils
Glib::Rand : classe pour la génération de nombres aléatoires basé sur
le Mersenne Twister. Il fournit les fonctions suivantes : get_bool(),
get_int(), get_int_range(), get_double(),. . .
Glib::Date : gestion des dates du calendrier julien, en vérifiant
l’existence réelle des dates.
Glib::Thread : gestion des threads dans les applications C++.
...
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
34 / 57
Glib::ustring
Cette classe existe pour combler un énorme défaut de la STL : elle ne
gère pas l’unicode UTF-8.
I
I
I
I
ISO : 8 bits, utilisé par Unix et un peu les autres : compatible ASCII et
ajoute les informations des pays, par exemple ISO8859-15 pour le
français avec le symbole euro.
UTF-16 : 16 bits, utilisé par Windows, un caractère prend deux octets
sur le système et n’est donc pas compatible avec l’ASCII.
UTF-32 : 32 bits, utilisé par Mac, un caractère prend quatre octects
sur le systèmes et n’est donc pas compatible avec l’ASCII.
UTF-8 : 8 bits minimum, 32 maximum. Utilisé de plus en plus car
compatible ASCII. La taille d’un caractère est calculée suivant son taux
d’utilisation dans les langues. ’a’ = 1, ’ç’ = 2, etc. La taille d’une
chaîne est obligatoirement calculée.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
35 / 57
Plan
1
gtkmm
La philosophie
La boucle événementielle
Les widgets
Les événements
2
glibmm , glade et libglademm
glibmm
glade
libglademm
3
Outils
pkg_config
Makefile
Les liens
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
36 / 57
Glade
Glade est une application qui permet de générer des interfaces graphiques.
Elles possèdent deux modes de fonctionnement :
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
37 / 57
Glade
Glade est une application qui permet de générer des interfaces graphiques.
Elles possèdent deux modes de fonctionnement :
Génération automatique de code, nécessite de possèder le programme
glademm qui génère le code C++. Problème chaque modification
d’un widget nécéssite la génération entière du projet.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
37 / 57
Glade
Glade est une application qui permet de générer des interfaces graphiques.
Elles possèdent deux modes de fonctionnement :
Génération automatique de code, nécessite de possèder le programme
glademm qui génère le code C++. Problème chaque modification
d’un widget nécéssite la génération entière du projet.
Génération d’un fichier d’extension glade qui contient l’interface
graphique du projet. Cette méthode est à privilégier car elle est plus
souple d’utilisation.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
37 / 57
Glade, le programme
Fig.: L’outil de développement d’interfaces graphiques, glade en version 2.6.8
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
38 / 57
Plan
1
gtkmm
La philosophie
La boucle événementielle
Les widgets
Les événements
2
glibmm , glade et libglademm
glibmm
glade
libglademm
3
Outils
pkg_config
Makefile
Les liens
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
39 / 57
libglademm
Le rôle de cette bibliothèque est de lire le fichier d’extension .glade et
de générer l’interface graphique en mémoire.
Une fois chargée, l’utilisateur peut récupérer des pointeurs sur les
éléments de l’interface graphiques.
On peut transformer un widget de l’arbre XML en classe dérivée de ce
widget.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
40 / 57
Exemple 1
1
2
# include < gtkmm .h >
# include < libglademm .h >
3
4
5
6
int main ( int argc , char ** argv ) {
Gtk :: Main application ( argc , argv );
Glib :: RefPtr < Gnome :: Glade :: Xml > xml ;
7
// une référence sur la hiérarchie de widgets créer
// par la libglademm .
xml = Gnome :: Glade :: Xml :: create ( " fenetre . glade " );
8
9
10
11
Gtk :: Window * w = 0;
12
13
// récupération d ’ une fenêtre .
xml - > get_widget ( " window " , w );
14
15
16
if ( w ) {
w - > show_all ();
application . run (* w );
}
17
18
19
20
21
}
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
41 / 57
Exemple 2 : explications
Dans l’exemple suivant, nous allons remplacer la fenêtre fournies par
la libglademm par une autre que nous avons définie dans une classe.
La bibliothèque libglademm fournie la fonction reparent_widget pour
placer le widget fourni en paramêtre dans un autre conteneur.
Cette technique n’est pas propre puisque deux fenêtres sont alors
chargées en mémoire dont une cachée.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
42 / 57
Exemple 2
class Fenetre : public Gtk::Window
{
public:
Fenetre();
private:
Gtk::VBox* v;
Gtk::Button b1, b2;
Gtk::Label* l;
Glib::RefPtr<Gnome::Glade::Xml> xml;
};
Fenetre::Fenetre() : v(0), b1("Ok"), b2("Annule"), l(0)
{
xml = Gnome::Glade::Xml::create("fenetre.glade");
xml->get_widget("vbox1", v);
xml->get_widget("label1", l);
// on déplace la VBox de l’instance générée par le fichier glade
// vers la fenêtre courante
xml->reparent_widget("vbox1", *this);
// on connecte deux boutons
b1.signal_clicked().connect(sigc::mem_fun(*this, &Gtk::Window::hide));
b2.signal_clicked().connect(sigc::mem_fun(*this, &Gtk::Window::hide));
v->add(b1); v->add(b2); v->show_all_children();
}
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
43 / 57
Transformation de widgets
Dans cette partie, nous allons utiliser la fonction get_widget_derived
qui permet de transformer un widget de l’arbre XML chargé en
mémoire dans une classe qui dérive de ce widget.
Dans Glade, les widgets utilisés sont des composants prédéfinis dans
la bibliothèque gtkmm . La fonction précédente va permettre de
transformer un objet dans un autre du moment qu’ils ont un héritage
commun.
L’exemple suivant montre la transformation de la fenêtre courante du
fichier glade dans une nouvelle classe DerivedDialog. Pour que cette
opération soit valide, gtkmm demande le développement d’un
constructeur particulier qui va lui permettre de construire l’objet
dérivé.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
44 / 57
Exemple 3
class DerivedDialog : public Gtk::Dialog
{
public:
// Le constructeur que la fonction demande obligatoirement
DerivedDialog(BaseObjectType* cobject,
const Glib::RefPtr<Gnome::Glade::Xml>& refGlade);
protected:
virtual void on_button_quit();
Glib::RefPtr<Gnome::Glade::Xml> m_refGlade;
Gtk::Button* m_pButton;
};
DerivedDialog::DerivedDialog(BaseObjectType* cobject,
const Glib::RefPtr<Gnome::Glade::Xml>& refGlade) :
Gtk::Dialog(cobject), m_refGlade(refGlade), m_pButton(0)
{
// On récupère un pointeur sur le bouton et on affecte la
// fonction virtuelle
m_refGlade->get_widget("quit_button", m_pButton);
if(m_pButton)
m_pButton->signal_clicked().connect(
sigc::mem_fun(*this, &DerivedDialog::on_button_quit));
}
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
45 / 57
Exemple 3 - suite
1
2
# include < gtkmm .h >
# include < libglademm .h >
3
4
5
6
int main ( int argc , char ** argv ) {
Gtk :: Main application ( argc , argv );
Glib :: RefPtr < Gnome :: Glade :: Xml > xml ;
7
// une référence sur la hiérarchie de widgets créer
// par la libglademm .
xml = Gnome :: Glade :: Xml :: create ( " dialog . glade " );
8
9
10
11
DerivedDialog * d = 0;
12
13
// récupération de la boîte de dialogue
xml - > g e t _ w i d g e t _ d e r i v e d ( " dialog " , d );
14
15
16
if ( d ) {
d - > show_all ();
application . run (* d );
}
17
18
19
20
21
}
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
46 / 57
Plan
1
gtkmm
La philosophie
La boucle événementielle
Les widgets
Les événements
2
glibmm , glade et libglademm
glibmm
glade
libglademm
3
Outils
pkg_config
Makefile
Les liens
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
47 / 57
pkg-config
Gère les chemins vers les bibliothèques et flags d’édition de liens pour
les bibliothèques compatibles installées sur le système.
La description des ces bibliothèques se trouvent dans le dossier :
/usr/lib/pkgconfig
Par exemple, la commande suivante affiche toutes les includes et
bibliothèques nécessaire à la compilation d’un fichier.
pkg-config –libs –cflags gtkmm-2.0
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
48 / 57
Plan
1
gtkmm
La philosophie
La boucle événementielle
Les widgets
Les événements
2
glibmm , glade et libglademm
glibmm
glade
libglademm
3
Outils
pkg_config
Makefile
Les liens
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
49 / 57
Makefile
make est un outils de gestion de fichiers, et pas seulement de fichier C.
make accepte une syntaxe type sh et donc tous les programmes
accessible par ce biais.
La syntaxe de make se gère en arbre de priorité. La tête de l’arbre se
nomme all
Le fonctionnement et le suivant :
but : [dépendances]
<tabulation> Comment réaliser le but.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
50 / 57
Makefile : un premier exemple
Un premier exemple de fichier Makefile pour compiler un programme
C écrit en cinq fichiers.
all : fichier1.o fichier2.o main.o
g++ -o executable fichier1.o fichier2.o main.o
fichier1.o : fichier1.c fichier1.h
g++ -c fichier1.c -Wall
fichier2.o : fichier2.c fichier2.h
g++ -c fichier2.c -Wall
main.o : main.c fichier1.h fichier2.h
g++ -c main.c -Wall
clean :
rm *~ *.o executable
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
51 / 57
taper make dans le console signifie make all, c’est-à-dire, utiliser
l’arbre de dépendance complet.
Taper make fichier1.o indique de n’utiliser que la branche de
dépendance fichier1.o donc générer ce fichier.
Taper make clean indique de n’utiliser que la branche clean,
c’est-à-dire, supprimer les fichiers destinations.
Taper make clean all appel l’arbre clean puis l’arbre all.
Example
Le prochain fichier Makefile utilise le programme pkg_config pour
récupérer les emplacements des bibliothèques de développement et leurs
noms.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
52 / 57
Exemple de fichier Makefile
CC=g++
CFLAGS=-Wall -W -g ‘pkg-config gtkmm-2.4 libglademm-2.4 –cflags‘
LFLAGS=‘pkg-config gtkmm-2.4 libglademm-2.4 –libs‘
OBJECTS=main.o application.o
HEADERS=application.hpp
TARGET=helloworld
all: $(TARGET)
$(TARGET):$(OBJECTS)
$(CC) $(LFLAGS) -o $(TARGET) $(OBJECTS)
%.o: %.cc
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJECTS) $(TARGET) *~
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
53 / 57
autotools GNU
Rendre les programmes portable en récupérant les paramètres du
compilateur, du système d’exploitation, des bibliothèques disponibles.
Permet la création de scripts de tests d’existence de bibliothèques ou
des fichiers.
Génération des fichiers Makefile automatiquement via des prototypes
de Makefile : Makefile.am.
Les programmes founis sont autoscan, autoheader, automake, aclocal
et autoconf.
Pour plus d’information reportez-vous aux documentations en lignes
du projet GNU.
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
54 / 57
Plan
1
gtkmm
La philosophie
La boucle événementielle
Les widgets
Les événements
2
glibmm , glade et libglademm
glibmm
glade
libglademm
3
Outils
pkg_config
Makefile
Les liens
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
55 / 57
Les liens
Une petite liste de liens :
gtkmm http://www.gtkmm.org
gtkmm le livre :
http://www.gtkmm.org/gtkmm2/docs/tutorial/html/index.html
gtk+ http://www.gtk.org
stl http://www.sgi.com/tech/stl/
C++ http://www.cplusplus.com/
faq C++ http://www.parashift.com/c++-faq-lite/index.html
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
56 / 57
Licence
Cours GTKmm
Copyright (C) 2007-2008 - VLE Development Team
{quesnel,eramat}@users.sourceforge.net
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
copy of the license is included in the section entitled "GNU Free
Documentation License".
G. Quesnel et E. Ramat (INRA et ULCO)
GTKmm
57 / 57
Téléchargement