Aller au menu - Aller au contenu

Icône Hello World

Avatar
Mise à jour : 31/07/2009
Difficulté : Facile Facile Creative Commons BY-NC-SA
808 visites depuis 7 jours, dont 80 sur ce chapitre classé 153/786
Nous allons dans cette partie créer notre premier petit programme. Pas de quoi sauter au plafond pour l'instant, il s'agit juste d'une introduction, mais il faut bien commencer par quelque chose ! :)
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Créons une petite GUI

GUI signifie Graphical User Interface, c'est un acronyme pour dire interface d'utilisateur. Comme c'est plus court, j'utiliserai désormais GUI. Dommage qu'il n'y ait pas la même chose pour widget, car je risque de l'écrire encore plus souvent...

Bon, prenez vos cahiers... Euh, votre concepteur. Dictée !

Pour notre premier programme qu'on appellera "Hello World !" pour respecter la tradition, nous allons utiliser les 3 types de widgets.

Et une fenêtre, une !



Commençons donc par ajouter une fenêtre. Cliquez juste sur le bouton fenêtre dans la palette, et elle devrait apparaître dans la zone de travail :

Image utilisateur


Dans les propriétés de la fenêtre, onglet "Général", nous allons lui donner un nom et un titre. Le nom nous servira à identifier le widget dans notre code Python, tandis que le titre correspondra au texte qui apparaîtra dans la barre en haut de notre fenêtre.

J'ai choisi comme nom "mainWindow" et comme titre "Hello World !" :

Image utilisateur


Autre réglage important, pour ne pas dire primordial, dans l'onglet "Commun" nous allons mettre la propriété "Visible" à la valeur "Oui".

Image utilisateur


Ne rigolez pas, mais une fois j'ai cherché pendant plusieurs heures pourquoi rien ne s'affichait quand je lançais mon programme... :lol: Quand j'ai compris pourquoi je m'en suis voulu.

Maintenant, faisons un tour dans l'énigmatique onglet "Signaux". Dans la partie GtkObject, à la ligne "destroy", nous allons écrire "on_mainWindow_destroy".

Image utilisateur


Ce que nous venons de faire doit vous paraître bien ésotérique, mais nous avons simplement attaché un gestionnaire à un signal. Quand notre fenêtre est détruite (par un clic sur le bouton fermer) elle émet un signal appelé "destroy". Dans notre code Python, une fonction appelée on_mainWindow_destroy() que nous écrirons nous-mêmes terminera notre programme.

Voilà pour la fenêtre.

Maintenant, une boîte verticale



Nous allons ensuite y ajouter une boîte verticale, ou GtkVBox pour les intimes. Dans la palette, section "Conteneurs", cliquez sur la "Boîte Verticale". Rien ne se passe, c'est normal. Il faut maintenant cliquer dans la fenêtre que nous venons de créer.

Si tout se passe bien, une boîte de dialogue vous demandant le nombre de lignes de la VBox apparaîtra :

Image utilisateur


Comme moi, choisissez 2.

Voilà maintenant voyons à quoi ressemble notre espace de travail :

Image utilisateur


Youpi ! ^^

Hello label !



Pour ceux qui l'ignorent, un label est simplement un morceau de texte.
Nous allons en ajouter un dans la ligne supérieure de notre VBox toute fraîche.

Pour cela on procède comme la dernière fois : dans la palette, section "Contrôle et affichage", cliquez sur le bouton représentant un label. Puis, dans la zone de travail, cliquez dans la partie haute de notre VBox.

Voilà notre label ajouté :

Image utilisateur


On va modifier un peu les propriétés de ce label. Dans l'onglet "Général", changez le nom pour "myLabel" et l'étiquette pour "Hello" :

Image utilisateur


Voilà pour le label. :-°

Un bouton



Ok, maintenant on ajoute un bouton dans la partie basse de la VBox. Je ne vais pas détailler la procédure une troisième fois, faites juste attention de ne pas confondre avec un "ToggleButton", car nous avons besoin d'un simple "Button". Comme ceci :

Image utilisateur


Il faut modifier ses propriétés.

Dans l'onglet "Général", changez le nom pour quelque chose de plus reconnaissable, du genre "myButton". Vous pouvez aussi changer l'étiquette, si ça vous tente. Mais ce dont ce bouton a vraiment envie, c'est que quand on clique dessus il se passe quelque chose ! Alors on va ajouter un gestionnaire à son signal "clicked" :

Image utilisateur


Ouf ! C'est fini ! :-°

On sauve notre travail



Sauvegardez tout ça dans un fichier Glade. J'ai nommé le mien "hello_world.glade".

Pour les tricheurs qui ne veulent pas suivre sérieusement ce tuto, voilà le résultat final :

Code : XML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0"?>
<interface>
  <requires lib="gtk+" version="2.16"/>
  <!-- interface-naming-policy project-wide -->
  <object class="GtkWindow" id="mainWindow">
    <property name="visible">True</property>
    <property name="title" translatable="yes">Hello World!</property>
    <signal name="destroy" handler="on_mainWindow_destroy"/>
    <child>
      <object class="GtkVBox" id="vbox1">
        <property name="visible">True</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkLabel" id="myLabel">
            <property name="visible">True</property>
            <property name="label" translatable="yes">Hello</property>
          </object>
          <packing>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkButton" id="myButton">
            <property name="label" translatable="yes">Mon bouton</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <signal name="clicked" handler="on_myButton_clicked"/>
          </object>
          <packing>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

Et notre script python

Dans le même dossier que votre hello_world.glade, vous allez créer un hello_world.py. Pour le rendre exécutable, faites un clic droit -> propriétés et cochez la case "Autorisez l'exécution du fichier comme un programme" :

Image utilisateur


Maintenant, ouvrez ce hello_world.py avec votre éditeur de texte préféré. Nous allons y écrire notre script. :)

J'ai fait le choix de vous donner le script déjà tout fini pour pouvoir le commenter ligne par ligne tout en ayant une vision globale du produit fini :

Code : Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/python
import pygtk
pygtk.require("2.0")
import gtk

class HelloWorld:
	def __init__(self):
		interface = gtk.Builder()
		interface.add_from_file('hello_world.glade')
		
		self.myLabel = interface.get_object("myLabel")
		interface.connect_signals(self)

	def on_mainWindow_destroy(self, widget):
		gtk.main_quit()

	def on_myButton_clicked(self, widget):
		self.myLabel.set_text("World!")

if __name__ == "__main__":
	HelloWorld()
	gtk.main()


Le fichier commence donc par cette ligne :

Code : Python
1
#!/usr/bin/python


Elle définit où trouver l'interpréteur Python qui lira et exécutera notre script. Tous les scripts Python commencent par une ligne du même genre. Ainsi, quand on exécutera notre fichier, le système saura quel programme devra le lire (dans notre cas, Python).

On a ensuite un bloc d'import :

Code : Python
1
2
3
import pygtk
pygtk.require("2.0")
import gtk


Ici, on importe simplement les modules dont on aura besoin pendant notre programme. Notez qu'on demande à PyGTK d'être au moins dans sa version 2.0.

Puis nous tombons sur ce gros bloc :

Code : Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class HelloWorld:
	def __init__(self):
		interface = gtk.Builder()
		interface.add_from_file('hello_world.glade')
		
		self.myLabel = interface.get_object("myLabel")
		interface.connect_signals(self)

	def on_mainWindow_destroy(self, widget):
		gtk.main_quit()

	def on_myButton_clicked(self, widget):
		self.myLabel.set_text("World!")


Il s'agit d'une classe. La classe "HelloWorld". Si vous n'avez jamais touché à la POO (Programmation Orientée Objet) sachez juste qu'il s'agit d'un sac dans lequel on range des fonctions qui ont un thème commun. Vous n'avez pas besoin de connaître la POO pour suivre ce tuto, et ça n'en est pas non plus le thème principal, donc je n'en dirai pas plus pour le moment.

Nous allons plutôt nous intéresser aux fonctions que cette classe contient, et qui constituent le corps de notre programme.

Nous avons donc une fonction __init__, qui se lance automatiquement au démarrage du programme. Dans cette fonction, et comme son nom l'indique, on va faire toutes sortes de tâches d'initialisation. :)

Code : Python
1
2
3
4
5
6
def __init__(self):
		interface = gtk.Builder()
		interface.add_from_file('hello_world.glade')
		
		self.myLabel = interface.get_object("myLabel")
		interface.connect_signals(self)


Et comme notre programme ne fait pas grand chose, c'est cette fonction qui est la plus grosse. Dans des programmes plus fournis, ce ne sera pas le cas.

Code : Python
1
2
interface = gtk.Builder()
interface.add_from_file('hello_world.glade')


Avec ces lignes, nous stockons notre fichier Glade dans une variable. C'est à partir de cette variable nommée interface que nous accéderons à nos widgets.

Code : Python
1
self.myLabel = interface.get_object("myLabel")


Ici, on stocke dans une variable self.myLabel notre widget myLabel pour pouvoir agir dessus plus tard. Par exemple en modifiant le texte qu'il contient. ;)

Code : Python
1
interface.connect_signals(self)


Cette ligne de code très importante va relier les signaux aux fonctions. Ainsi, quand on fermera la fenêtre, la fonction self.on_mainWindow_destroy sera exécutée. De même, quand on cliquera sur le bouton, la fonction self.on_myButton_clicked sera exécutée. On appelle cela de la programmation événementielle : le programme tourne en boucle en attendant un événement. Puis un jour, quelqu'un clique sur le bouton. Le programme reçoit un signal, et agit en conséquence. :)
En fait, cette ligne connecte tous les signaux que l'on a précisés dans le concepteur Glade si les méthodes sont dans la même classe (les fonctions et méthodes à l'extérieur ne seront pas trouvés par cette méthode). Les méthodes créées doivent porter le même nom que l'on a mis dans Glade. Dans le concepteur, nous avions préciser le gestionnaire on_mainWindow_destroy pour le signal destroy de notre fenêtre. Grâce à Gtk.Builder, lorsque le signal destroy est émit, la fonction on_mainWindow_destroy, ou la méthode self.on_mainWindow_destroy selon les cas, sera appelée lors de l'émission du signal.
Et si la fonction se trouve à l'extérieur, ou si je n'utilise pas le POO, comment faire pour relier le gestionnaire à une fonction ?

Eh bien, il faudra écrire autre chose que self : un dictionnaire.
Exemple :
Code : Python
1
interface.connect_signals({'quitter' : quitter, 'changerTexte' : self.changerTexte})

Ici, la fonction quitter n'est pas dans la classe et la méthode self.changerTexte l'est.
Mais, cela a l'inconvénient d'avoir à écrire toutes les fonctions une à une.

Fin de la fonction __init__. Le programme est initialisé, plus rien ne se passe... Plus rien ? Sauf si on appuie sur le bouton, ou qu'on ferme la fenêtre !!!

Passons maintenant à la fonction on_mainWindow_destroy, fonction qui est appelée quand on ferme la fenêtre :

Code : Python
1
2
def on_mainWindow_destroy(self, widget):
	gtk.main_quit()


Elle contient juste gtk.main_quit() qui a pour effet d'arrêter le programme.

Mais le programme ne s'arrête pas automatiquement quand on ferme la fenêtre ?

Eh bien en apparence oui. :)
La fenêtre se ferme bien, mais en fait le programme continue de tourner tout seul, dans l'invisible en arrière-plan !

On arrive maintenant à la fonction qui fait effet :

Code : Python
1
2
def on_myButton_clicked(self, widget):
	self.myLabel.set_text("World!")

Alors d'après vous, que fait cette fonction ?
Elle change le texte de notre label bien sûr. :D

Voilà, nous avons fini d'étudier notre classe "HelloWorld".

Il ne nous reste que ce petit bout de code à voir :

Code : Python
1
2
3
if __name__ == "__main__":
	HelloWorld()
	gtk.main()

Il sert juste à lancer notre classe HelloWorld.
La dernière instruction gtk.main() est une boucle infinie qui empêche notre programme de se fermer dès son lancement.

Bon, on essaye de le lancer ?

Oui oui, lançons-le, ce magnifique programme ! :)

Mais on va le lancer dans le terminal pour avoir droit au débuggeur de Python en cas de problème.

Rendez-vous donc, avec le terminal, dans le dossier contenant vos deux fichiers (chez moi ils sont sur le bureau) :

Code : Console
cd Bureau/


Puis lancez notre programme comme ceci :

Code : Console
python hello_world.py


Si tout se passe bien, vous verrez dans un coin de l'écran notre minuscule fenêtre apparaître.
Tiens, c'est bizarre, elle n'était pas un peu plus grande dans le concepteur ? Elle a rétréci au lavage ou quoi ?

C'est juste que nous n'avons pas défini de dimension minimale pour la fenêtre. Mais je suis sûr que vous avez le niveau pour le faire maintenant. :)

Voilà notre programme une fois redimensionné par nos soins :

Image utilisateur


Et quand on appuie sur le bouton : surprise !!! :D

Image utilisateur

Q.C.M.

Que signifie GUI ?
Quel attribut d'un widget permet de l'identifier dans votre code Python ?
Quel(s) module(s) doi(ven)t forcément être importé(s) pour utiliser PyGTK ?
À quoi sert la méthode connect_signals() ?
Que faut-il faire pour avoir accès aux messages d'erreur (liés à PyGtk) de notre programme ?
Quelle méthode sert à récupérer un widget dans un Gtk.Builder() ?

Statistiques de réponses au QCM

Dans le chapitre précédent, vous avez vu comment créer la partie visuelle de votre programme. Maintenant, vous savez comment faire pour lier cette partie à du code Python. Vous avez appris comment relier l'émission d'un signal à une fonction. Sachez que vous ne pourrez plus vous passez des signaux : ils sont le coeur des programmes PyGtk (pensez-y, comment faire pour interagir avec un utilisateur sans les signaux). Dans le prochain chapitre, vous verrez comment faire une fenêtre sans Glade.
Chapitre précédent Sommaire Chapitre suivant

Partager

3 commentaires pour "Hello World"
Note moyenne : 3.59 / 4 (17 votes)
Pseudo Commentaire
Hors ligne SwimFan # Posté le 02/01/2010 à 16:04:58
SwimFan corp.
Avatar

Bonjour, merci pour ce tuto, tres bien fait

Toutefois, n'étant pas sur linux, je rencontre un probleme lors de l'execution du hello world.

J'ai créé un topic expliquant le probleme : http://www.siteduzero.com/forum-83-475 [...] us-vista.html

Merci encore
Hors ligne informaticous # Posté le 01/07/2010 à 12:59:54
Avatar

Ville : Brain le comte
Pays : Belgique

Superbe tuto, dommage qu'il ne soie pas a jours.
Hors ligne vbrandersv # Posté le 12/08/2011 à 10:41:56

Études : Université Libre de Bruxelles (ULB)

Salut, je ne comprends pas ce qui ne va pas, j'ai bien coché les largeur et hauteur par défaut et donné des valeurs, mais la fenêtre reste toute petite... ou est 'erreur ?

Image utilisateur
 

Voir tous les commentaires
Ce tutoriel a été corrigé par les zCorrecteurs.