Aller au menu - Aller au contenu

Icône Les widgets suite (Partie 1)

Avatar
Mise à jour : 31/07/2009
Difficulté : Facile Facile Creative Commons BY-NC-SA
808 visites depuis 7 jours, dont 47 sur ce chapitre classé 153/786
Comme le chapitre précédent est un TP, je vais vous montrer des widgets relativement simples d'utilisation.
Continuons notre apprentissage des widgets !
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire

Les images

Présentation


Les gtk.Image() permettent d'afficher des images dans une fenêtre PyGtk.

Construction


Il est très simple de créer un gtk.Image() et de l'utiliser.
Code : Python
1
image = gtk.Image()

Hé ! J'ai ajouté ce widget à ma fenêtre et je ne vois rien dans celle-ci. Qu'est-ce que j'ai fait de mal ?

Il faut, soit charger une image à partir d'un fichier, soit la charger à partir d'un Stock Item (on peut en charger une à partir d'autres choses, mais je n'en parlerai pas. Allez voir la doc' :D )

Utilisation


Pour charger une image à partir d'un fichier, il faut utiliser la méthode suivante :
Code : Python
1
image.set_from_file('image.png')

Et à partir d'un Stock Item :
Code : Python
1
image.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_SMALL_TOOLBAR)

Le premier paramètre est le Stock Item et le second est sa taille.
C'est l'une des constantes que vous pouvez trouvez vous savez où.

Dans le Concepteur d'Interface Glade


Il est très facile de créer une image dans le Concepteur d'Interface Glade. Il faut choisir l'icône Image (Image utilisateur) et la mettre où l'on veut. Ensuite, sous l'onglet Général, il faut choisir une des trois options suivantes, dessous Modifier l'image :
  • ID du stock
  • Nom de l'icône
  • Nom de fichier

Les cadres

Présentation



Les cadres ou gtk.Frame sont des conteneurs simples qui n'ont qu'un enfant. Ils servent juste à "encadrer" le widget fils. Le principal intérêt de ce widget est donc esthétique.
Vous pouvez voir ici un cadre que j'ai créé avec le concepteur. Je lui ai mis un rebord visible pour que vous compreniez mieux de quoi il s'agit :

Image utilisateur


Dans la zone de propriétés, onglet général, vous pouvez régler le type de bordure ainsi que le titre du cadre :

Image utilisateur


Si vous essayez de créer un cadre dans le concepteur, vous remarquerez que celui-ci est automatiquement créé avec un widget d'alignement comme enfant :

Image utilisateur


Ce widget a pour effet (et pour but premier) de décaller son contenu vers la droite. Vous pouvez le supprimer s'il vous dérange. Notez que quand on crée un gtk.Frame directement en pyGTK pur, ce widget d'alignement n'est pas ajouté. Son ajout est strictement dû au concepteur.

Construction



Comme ceci :

Code : Python
1
cadre = gtk.Frame("Titre du cadre")


Vous pouvez créer un cadre sans titre en ne mettant rien dans les parenthèses.

Méthodes



set_label



Pour modifier le titre :

Code : Python
1
cadre.set_label("Nouveau titre")


set_label_widget



Pour mettre n'importe quel widget à la place du texte du titre :

Code : Python
1
cadre.set_label_widget(gtk.Button("Clique moi"))


set_shadow_type



Pour changer le type de la bordure :

Code : Python
1
cadre.set_shadow_type(type)


type peut valoir :
  • gtk.SHADOW_NONE
  • gtk.SHADOW_IN
  • gtk.SHADOW_OUT
  • gtk.SHADOW_ETCHED_IN
  • gtk.SHADOW_ETCHED_OUT


set_label_align(xalign, yalign)


C'est l'alignement horizontal et vertical de l'étiquette sur le cadre supérieur.
Si l'on veut que l'étiquette soit au centre horizontalement et verticalement par rapport au cadre, il faut faire ceci :
Code : Python
1
cadre.set_label_align(0.5, 0.5)

Si l'on veut qu'il soit au centre horizontalement et à l'extérieur du cadre, ceci :
Code : Python
1
cadre.set_label_align(0.5, 1)

Si l'on veut qu'il soit à droite et à l'intérieur du cadre, ceci :
Code : Python
1
cadre.set_label_align(1, 0)

Donc, pour xalign, plus il est grand, plus l'étiquette sera à droite.
Et pour yalign, plus il est grand, plus l'étiquette sera haute (alors, elle sera plus à l'extérieur).

add



...et add() pour ajouter un enfant bien sur !

Les cadres d'apparence

Les cadres d'apparence, gtk.AspectFrame pour les intimes, ressemblent à ça :

Image utilisateur


Vous pouvez voir qu'ils partagent pas mal de propriétés avec gtk.Frame. C'est bien normal, car gtk.AspectFrame dérive de gtk.Frame et hérite donc de ses propriétés et méthodes.

Image utilisateur


En regardant de plus près on constate que ces cadres ne peuvent pas avoir de titre dans le concepteur Glade, mais ils peuvent en avoir en PyGTK pur (étrange, non ?).

Ils ont une propriété "Ratio" qui représente le rapport fixe entre la largeur et la hauteur du cadre. C'est leur utilité principale : garder un rapport fixe entre largeur et hauteur, afin que le widget enfant ai toujours les même proportions.
C'est la seule différence avec les gtk.Frame() (mis à part le fait qu'on ne peut pas mettre d'étiquette dans le concepteur).
Encore un widget esthétique donc.

Construction



Code : Python
1
cadre = gtk.AspectFrame(label=None, xalign=0.5, yalign=0.5, ratio=1.0, obey_child=True)

Le label est l'étiquette. Nous avons déjà vu xalign et xalign dans les gtk.Frame(), mais ils n'ont pas le même effet.
Ici, ils sont l'alignement du widget dans son parent de xalign = 0 et yalign = 0 (en haut à gauche) jusqu'à xalign = 1 et yalign = 1 (en bas à droite).
Par défaut, xalign = 0.5 et yalign = 0.5. Voici ce que ça donne :
Image utilisateur

Tu m'avais dit que par défaut il est centré. Or, ici il est seulement centré horizontalement. Quel est le problème ?

Vous avez raison de dire cela : il ne peut seulement être centré (dans le cas présent) que dans un sens (horizontalement ou verticalement) et non dans les deux.
Devinez-vous pourquoi ?
Parce que le cadre prend toute la place dans la fenêtre. Alors, il ne pourra pas être centré horizontalement et verticalement.

ratio est la proportion. Avec une proportion de 0.5, j'obtiens ceci :
Image utilisateur

Le ratio peut aller de 0.0001 à 10000.0. Impressionnant, non :euh: ?

J'ai suivi tout ce que tu as dit et j'ai mis un ratio de 0.5, mais je n'obtiens pas la même chose que toi. Qu'est-ce que j'ai fait de mal ?

Je ne vous ai toujours pas parlé du dernier paramètre ; il est très important. Je me demande d'ailleurs pourquoi il vaut True par défaut. Pour que le ratio soit pris en compte, il faut le mettre à False (obey_child = False).

Méthodes


set


Modifie les propriétés du cadre d'apparence :

Code : Python
1
cadre.set(xalign=0.0, yalign=0.0, ratio=1.0, obey_child=True)


C'est la seule méthode de gtk.AspectFrame(). La seule ?
N'oubliez pas celles de sont parent gtk.Frame, et de tous ces ancêtres !

La barre de progression

Présentation


La barre de progression est un widget qui indique un progrès quelconque de façon visible :
Image utilisateur

Comme vous pouvez le constater, c'est bien plus visible que d'afficher seulement 40%.

Construction


Nous construisons une barre de progression comme ceci :
Code : Python
1
barreProgression = gtk.ProgressBar()


Utilisation


Voyons, à travers un exemple, comment utiliser un gtk.ProgressBar() :
Code : Python
 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
# -*- coding:Utf-8 -*-
import pygtk
pygtk.require("2.0")
import gtk

def ajouter(widget, barreProgression):
	progression = barreProgression.get_fraction() #Obtenir le pourcentage (sur 1.0)
	if progression < 1:
		barreProgression.set_fraction(progression + 0.1) #Définir un nouveau pourcentage
	else:
		barreProgression.set_fraction(0)
	progression = barreProgression.get_fraction()
	texte = "Progression en cours - " + str(int(progression * 100)) + "%"
	barreProgression.set_text(texte)

fenetre = gtk.Window(gtk.WINDOW_TOPLEVEL)
fenetre.set_title("Barre de progression")
fenetre.set_default_size(320, 180)
fenetre.set_position(gtk.WIN_POS_CENTER)
fenetre.connect("destroy", gtk.main_quit)

boiteV = gtk.VBox()
fenetre.add(boiteV)

barreProgression = gtk.ProgressBar() #Création d'une barre de progression
barreProgression.set_text("Progression en cours - 0%") #Définir un texte pour la barre
boutonAjouter = gtk.Button(stock = gtk.STOCK_ADD)
boutonAjouter.connect("clicked", ajouter, barreProgression)
boiteV.pack_start(barreProgression, False, False, 10)
boiteV.pack_end(boutonAjouter, False, False, 0)

fenetre.show_all()

gtk.main()

Au début du programme, on importe les bibliothèques.
Ensuite, je crée la fonction ajouter : dans celle-ci, j'obtiens premièrement le pourcentage de la barre de progression avec a méthode get_fraction() (ce pourcentage est de 0 à 1, donc 50% égale 0.5).
Puis, si le pourcentage est inférieur à 100%, je l'augmente de 10%, sinon, je le remets à 0%, avec la méthode set_fraction().
Après, j'obtiens le nouveau pourcentage pour pouvoir changer le texte apparaissant sur la barre de progression à l'aide de la méthode set_text().

Le reste est la création de la fenêtre, ayant une barre de progression et un bouton qui ajoute, à l'aide de la fonction précédemment créée, 10% à la barre de progression.

Dans le Concepteur d'Interface Glade


L'icône de la barre de progression est celle-ci : Image utilisateur
Après avoir mis la barre de progession où vous voulez, vous pouvez changer sa Fraction (pourcentage ; toujours de 0 à 1) et son Texte sous l'onglet Général. Vous pouvez également changer d'autres choses comme son orientation (de gauche à droite, de haut en bas, de bas en haut et de droite à gauche).
Cela pourrait donc donner ceci :
Image utilisateur

Les listes déroulantes

Présentation


La liste déroulante est une zone à options différentes des cases à cocher et des boutons radio. Dans les listes déroulantes, nous ne voyons que l'élément choisi et lorsque l'on clique dessus, on les voit toutes et on peut changer l'élément choisi. En voici une :
Image utilisateur


Construction


Nous construisons une liste déroulante d'une façon un peu... anormale :
Code : Python
1
listeDeroulante = gtk.combo_box_new_text()

Cette méthode de création est plus facile d'utilisation que celle=ci :
Code : Python
1
listeDeroulante = gtk.ComboBox()

que je vous déconseille pour l'instant, car il faudra créer un modèle, ce que nous n'avons pas encore vu.

Utilisation


Méthodes


Voici les principales méthodes utilisées avec les listes déroulantes :
  • append_text(text) : ajoute un élément à la liste
  • set_active(index) : changer d'élément choisi
  • get_active_text() : renvoie le texte de l'élément actif

Signal


Nous voyons ici un nouveau signal : il s'agit de 'changed' qui est émit lorsque l'utilisateur change d'élément.

Utilisation avec Glade


Je vais vous montrer comment en une avec Glade. Par contre, il faudra utiliser des modèles, mais ne vous en faites pas, ce sera facile.

Dans une fenêtre, ajouter une liste déroulante (Image utilisateur - appelé Boîte combinée dans le concepteur).
Sélectionnez-la et, dans l'onglet Général, cliquez sur le bouton '...' suivant les mots Modèle de ComboBox :. Dans la boîte de dialogue qui s'ouvre, cliquez sur Nouveau et cette boîte se ferme : vous venez de créer un nouveau modèle.
Vous pouvez constater qu'il y a un nouvel élément dans l'arbre, sous le mot Objets : liststore1.
C'est notre nouveau modèle : sélectionnez-le.
Cliquez sur le premier élément de la liste sous Ajouter et enlever des colonnes :.
Ensuite, cliquez sur la petite flèche qui pointe vers le bas et choisissez dans la liste déroulante le mot gchararray (il se trouve plutôt vers le haut de la liste).

Allez plus bas et cliquez sur le bouton + suivant les mots Ajouter et enlever des lignes : : une nouvelle ligne apparaît. Vous pouvez changer sont texte en cliquant dessus. Faites-en plusieurs dont une qui a pour texte "Quitter" (ajouter le texte sans les guillemets).

Maintenant, dans la zone de travail, il est possible de cliquer sur la liste déroulante, mais vous ne verrez rien. Il manque quelque chose : il faut ajouter la colonne que nous venons de créer dans cette liste, mais pas les rangées qui font partie de la colonne :o .

Pour cela, faites un clique-droit sur votre liste déroulante (gtk.ComboBox) et choisissez "Edit...". Allez dans l'onglet Hiérarchie.
Est-ce que cela vous rappelle quelque chose ?
He oui, c'est la même que pour les menus et les barres d'outils !

Cliquez sur le bouton Ajouter : un nouvel élément apparaît dans la liste, choisissez-le !
Dans ces Propriétés et attributs, cliquez sur la liste déroulante suivant le mot Texte : (il faut utiliser beaucoup de listes déroulantes pour en créer une, vous ne trouvez pas ?) et choisissez la colonne que nous avons créer plus tôt (elle a un nom du genre gchararray1). Fermer la boîte de dialogue.

Maintenant, notre liste déroulante est terminée. Les rangées sont supposées apparaître dans la liste déroulante dans la zone de travail de Glade, mais, des fois, elles ne veulent pas apparaître. Ne vous en faites pas, dans votre programme, elles apparaîtront.
Et si vous redémarrez Glade, elles apparaîtront.

Il ne nous reste qu'une petite chose à faire. Sélectionnez notre liste déroulante et allez dans l'onglet Signaux.
Pour le signal 'changed', mettez le gestionnaire 'choix'.

Allons coder maintenant !
Voici le code :Code : Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# -*- coding:Utf-8 -*-
import pygtk
pygtk.require("2.0")
import gtk

class PyGtkApp:
	def __init__(self):
		interface = gtk.Builder()
		interface.add_from_file('listeDeroulante.glade')
		
		interface.connect_signals(self)
	
	def choix(self, widget):
		if widget.get_active_text() == 'Quitter':
			gtk.main_quit()
	
	def quitter(self, widget):
		gtk.main_quit()
	
PyGtkApp()
gtk.main()

Il n'y a rien de nouveau. La méthode get_active_text() fonctionne toujours parce que c'est du texte.
Votre programme ne fera rien si vous n'avez pas ajouter une rangée contenant le mot Quitter.
Mais, s'il a la rangée Quitter, le programme se fermera lorsque vous la choisirez.

Les règles

Présentation


Les règles sont utilisées pour que l'utilisateur puissent connaître les dimensions d'un certain widget et où se trouve la souris sur celui-ci. Elles sont utilisées par le logiciel GIMP. Elles peuvent donc vous être utiles si vous souhaitez faire un éditeur d'image.

Construction


Comme vous vous en doutez, il y a des règles verticales et des règles horizontales.
La construction d'une règle verticale se fait comme ceci :
Code : Python
1
regleV = gtk.VRuler()

Et celle d'une règle horizontale :
Code : Python
1
regleH = gtk.HRuler()


Utilisation


Nous allons voir, à travers un exemple, comment utiliser les règles.
Commençons par importer les bibliothèques nécessaires :
Code : Python
1
2
3
4
# -*- coding:Utf-8 -*-
import pygtk
pygtk.require("2.0")
import gtk

Ensuite, créons notre fenêtre :
Code : Python
1
2
3
4
5
fenetre = gtk.Window()
fenetre.set_title("Les règles")
fenetre.set_default_size(640, 480)
fenetre.set_position(gtk.WIN_POS_CENTER)
fenetre.connect("destroy", gtk.main_quit)

Maitenant, attaquons nous à son contenu :
On va insérer une zone de texte multiligne avec une règle horizontale et une verticale. Tout ceci sera dans un tableau :
Code : Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
tableau = gtk.Table(2, 2)
zoneTexteMultiligne = gtk.TextView()
tableau.attach(zoneTexteMultiligne, 1, 2, 1, 2)
regleH = gtk.HRuler() #Création d'une règle horizontale
regleH.set_range(0, 640, 0, 640) #Définir le minimum, le maximum et la position courante
tableau.attach(regleH, 1, 2, 0, 1, yoptions = 0)
regleV = gtk.VRuler() #Création d'une règle verticale
regleV.set_range(0, 480, 0, 480)
tableau.attach(regleV, 0, 1, 1, 2, xoptions = 0)
fenetre.add(tableau)

À la ligne 1, on crée un tableau de 2 * 2 cases.
À la seconde ligne, on crée la zone de texte et, à la troisième, on l'insère dans le tableau.
À la quatrième ligne, on crée une règle horizontale et, à la suivante, on définit ses extrêmes.
À la sixième ligne, on l'insère dans le tableau avec un yoptions de 0 (pour que la règle ne prenne pas autant de place que les autres éléments dans le tableau)
Ensuite, on fait pareil avec une règle verticale (attention, c'est fois, c'est un xoptions de 0) et on ajoute le tableau à la fenêtre.
Voyons en détail la méthode set_range(), la méthode qui définit les extrêmes :
Code : Python
1
def set_range(lower, upper, position, max_size)

  • lower est la valeur minimale de la règle (la valeur la plus à gauche ou en haut) ;
  • upper est la valeur maximale de la règle (la valeur la plus à droite ou en bas) ;
  • position est la position de départ de la règle (je mets en général 0) ;
  • max_size est une valeur qui déterminera l'écart entre les mesures affichés (je mets en général la même donnée que upper).

Finalement, on affiche tout et on démarre la boucle :
Code : Python
1
2
3
fenetre.show_all()

gtk.main()

Hé ! J'ai tout fait ce que tu as dit et la petite flèche qui apparaît sur les règles ne bougent que lorsque la souris bouge sur celles-ci. Je voudrais qu'elle bouge aussi lorsque la souris passe sur la zone de texte. Comment faire ?

Il va falloir ajouter un signal sur la zone de texte : le signal "motion_notify_event", qui est émit lorsque la souris bouge sur un widget.
Donc, il vous faut ajouter ceci au code :
Code : Python
1
2
zoneTexteMultiligne.set_events(gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK) #Génère un événement après avoir bouger la souris
zoneTexteMultiligne.connect("motion_notify_event", modifieValeursRegle, regleH, regleV) #Lorsque la souris a bougé sur un widget

La première ligne indique que le widget génèrera un événement après avoir bouger la souris et la seconde appelle une fonction lorsque la souris bouge. Voici la fonction modifieValeursRegle :
Code : Python
1
2
3
def modifieValeursRegle(widget, event, regleH, regleV):
	regleH.emit("motion_notify_event", event) #On cause un événement (mouvement de la souris) chez la règle pour qu'elle prenne en compte ces mouvements.
	regleV.emit("motion_notify_event", event)

Si la flèche bouge sur la règle, c'est parce qu'un signal est émit, donc émettons ce même signal lorsque la souris bouge sur la zone de texte.

Les sélecteurs de valeurs numériques

Présentation


Les sélecteurs de valeurs numériques sont des widgets qui permettent à l'utilisateur de choisir une valeur. Il y a en plusieurs sortes : il y a le bouton compteur (une zone de texte à une ligne qui comporte des flèches pour augmenter et diminuer la valeur), le curseur horizontal et le curseur vertical.
Image utilisateur Image utilisateur Image utilisateur
bouton compteur | curseur horizontal | curseur vertical


Bouton compteur


Construction


Pour chacun de ces widgets, il faudra créer un autre widget pour définir les valeurs minimales, maximales et d'autres valeurs. Ce widget est le gtk.Adjustment et il se crée comme suit :
Code : Python
1
ajustement = gtk.Adjustment(0, 0, 1000, 1, 8)

La première valeur est la valeur initiale (la valeur affichée lorsque l'on ouvre le programme).
La seconde est la valeur minimale et la troisième est celle maximale.
La quatrième est l'incrémentation.
Qu'est-ce que l'incrémentation ?

L'incrémentation est la valeur ajoutée à chaque fois que l'on augmente la valeur du sélecteur de valeur numérique, soit avec les flèches du clavier si le widget a le focus, soit avec la souris (en l'occurence, en appuyant sur les petites flèches à droite du bouton compteur).
La cinquième est l'incrémentation Page Up. C'est l'incrémentation qui sera effectué lorsque l'utilisateur appuiera sur les touches Page Up ou Page Down. Dans le cas de Page Down, ce sera de la désincrémentation. On ne précise que l'incrémentation pour les paramètres 4 et 5, mais pas la désincrémentation. Ce sera la même, mais en négatif.

Après avoir créer l'ajustement, on peut enfin créer notre bouton compteur :
Code : Python
1
selecteur = gtk.SpinButton(ajustement)

Le seul paramètre est l'ajustement précédemment créé.

Méthodes


Il y a deux méthodes dont j'aimerais vous parler :
  • set_numeric(numeric) : si numeric vaut True, seuls les chiffres pourront être écrits dans la zone de texte ;
  • get_value() : renvoie la valeur choisi dans le sélecteur de valeur numérique.


Les curseurs horizontaux et verticaux


Construction


Je ne vais pas vous répéter les instructions sur les ajustements, vous les savez déjà. C'est presque la même chose que précédemment ; il n'y a que le nom de la classe qui change :
Code : Python
1
scaleH = gtk.HScale(ajustement)

Vous devinez comment faire avec un curseur vertical, j'espère :-°

Méthodes


get_value() est aussi une méthode de ce widget et fonctionne comme pour le bouton compteur.
Une autre méthode dont j'aimerais vous parler est set_digits(digits)digits est le nombre de décimales à afficher. Cette méthode fonctionne également avec les boutons compteur.

Notez qu'il y a d'autres méthodes pour ces widgets et vous pouvez les trouvez dans la documentation.

Divers

Le bouton du volume


Le bouton du volume ressemble beaucoup aux curseurs que nous venons de voir. En fait, il hérite de ceux-ci. Donc, les méthode et le signal que nous verrons sur le bouton du volume fonctionne aussi avec les curseurs.

Pour créer un tel bouton, il faut faire comme suit :
Code : Python
1
boutonVolume = gtk.VolumeButton()


Mais, si on l'affiche, nous n'avons pas le volume du système. Pour le connaître, il faut importer un module supplémentaire (à mettre au début du fichier) :
Code : Python
1
import ossaudiodev


Comme le volume du système est de 0 à 100, il faut changer l'ajustement du bouton :
Code : Python
1
2
ajustement = gtk.Adjustment(0, 0, 100, 1, 10) #Création d'un ajustement de 0 à 100
boutonVolume.set_adjustment(ajustement)

On crée un ajustement et on change l'ajustement du bouton.

Ensuite, il faut changer la valeur du bouton :
Code : Python
1
2
mixer = ossaudiodev.openmixer() #Création d'un mixer
boutonVolume.set_value(mixer.get(ossaudiodev.SOUND_MIXER_VOLUME)[0])

À la première ligne, nous créons un mixer pour pouvoir obtenir le volume.
À la seconde, on change la valeur du bouton avec la méthode set_value() et mixer.get(ossaudiodev.SOUND_MIXER_VOLUME)[0] nous donne le volume.

Maintenant, on veut que lorsque l'on change le volume sur le bouton, que ça change le volume du système :
Code : Python
1
boutonVolume.connect('value-changed', changerVolumeSysteme)

On voit un nouveau signal ('value-changed') qui est émit lorsque l'on bouge le curseur.

Voyons la fonction changerVolumeSysteme:
Code : Python
1
2
def changerVolumeSysteme(widget, volume):
	mixer.set(ossaudiodev.SOUND_MIXER_VOLUME, (int(volume), int(volume)))

On change le volume du système avec mixer.set().

Une horloge numérique


Ce n'est pas vraiment un widget, mais je voulais quand même vous montrer comment faire une horloge numérique. Si je vous demanderais de faire une horloge numérique (où le temps se met à jour à toutes les secondes), vous en seriez incapables. C'est pourquoi je vous montre comment faire. Vous apprendrez à utiliser une boucle qui ne bloquera pas le programme. Elle s'exécutera en parallèle à la boucle principale.

Premièrement, on importe les bibliothèques nécessaires :
Code : Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# -*- coding:Utf-8 -*-

import pygtk

pygtk.require("2.0")

import gtk

import gobject

from time import *

Le module gobject nous servira pour pouvoir exécuter une boucle en parallèle et le module time, pour connaître la date et l'heure.

Deuxièmement, on crée notre classe principale et la fenêtre :
Code : Python
1
2
3
4
5
6
7
class Horloge(gtk.Window):
	def __init__(self):
		super(Horloge, self).__init__()
		
		self.set_title("Horloge en temps réel")
		self.set_default_size(320, 180)
		self.set_position(gtk.WIN_POS_CENTER)

Ensuite, on crée quelques variables :
Code : Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#Puisque la fonction localtime() donne des chiffres, il faut les convertir en mots grâce à ces tuples
		self.jours = ('Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche')
		self.mois = ('', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre')
		
		if localtime()[4] < 10: #Si les minutes sont inférieurs à 10, on ajoute un 0 pour que l'affichage soit comme ceci 13:01.05 au lieu de 13:1.5
			minutes = "0" + str(localtime()[4])
		else:
			minutes = str(localtime()[4])

		if localtime()[5] < 10:
			secondes = "0" + str(localtime()[5])
		else:
			secondes = str(localtime()[5])

On crée des tuples qui conresponderont avec les valeurs que localtime() donne pour pouvoir changer les chiffres des jours de la semaine et des mois en mots.
Enfin, si les minutes et les secondes sont inférieurs à 10, on ajoute un 0, de sorte que 13:05.04 soit affiché à la place de 13:5.4 qui est moins esthétique.

Puis, on crée les chaînes de caractères qui s'afficheront dans un gtk.Label() :
Code : Python
1
2
3
4
5
6
7
8
temps = 'Il est ' + str(localtime()[3]) + ':' + minutes + '.' + secondes + '.'
		date = 'Nous sommes ' + self.jours[localtime()[6]] + ', le ' + str(localtime()[2]) + ' ' + self.mois[localtime()[1]] + ' ' + str(localtime()[0]) + '.'
		self.etiquette = gtk.Label(temps + '\n' + date)
		self.add(self.etiquette)
		
		self.connect("destroy", gtk.main_quit)
		self.show_all()
		gobject.idle_add(self.metAJourTemps) #C'est grâce à ceci que l'on peut ajouter une boucle parallèle à la boucle principale

Après, on ajoute l'étiquette à la fenêtre, on connecte la fenêtre à la méthode gtk.main_quit() et on affiche tous les widgets.
À la dernière ligne, on utilise la méthode idle_add du module gobject avec comme paramètre la méthode (ou fonction, selon les cas) qui sera appeller indéfiniment. Si cette méthode retourne True, la boucle continue, si elle renvoie False, elle s'arrête. Elle s'arrête aussi lors de l'appel de gtk.main_quit().

Et finalement, la dernière méthode :
Code : Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def metAJourTemps(self):
		if localtime()[4] < 10:
			minutes = "0" + str(localtime()[4])
		else:
			minutes = str(localtime()[4])
			
		if localtime()[5] < 10:
			secondes = "0" + str(localtime()[5])
		else:
			secondes = str(localtime()[5])
			
		temps = 'Il est ' + str(localtime()[3]) + ':' + minutes + '.' + secondes + '.'
		date = 'Nous sommes ' + self.jours[localtime()[6]] + ', le ' + str(localtime()[2]) + ' ' + self.mois[localtime()[1]] + ' ' + str(localtime()[0]) + '.'
		self.etiquette.set_text(temps + '\n' + date)
		sleep(1) #On attend un seconde avant de refaire la boucle de nouveau
		return True #Si le retour est True, la boucle continue

La première partie de ce code est du déjà-vu. Ensuite, on fait attendre le programme 1 seconde (avec sleep(1)) pour que la mise à jour du texte ne se fasse qu'à chaque seconde (cela consomme moins de ressource ; chez moi, il consomme 20% à 40% du CPU sans cette appel et 0% avec).
On retourne True et la boucle continue. Elle s'arrête lors de l'appel de gtk.main_quit() ou lorsqu'elle revoie False.

Une icône dans la barre des tâches


Certains programmes ont une icône qui est affichée dans la barre des tâches (sous Windows et KDE, l'icône se situera en bas à droite et sous GNOME, en haut à droite).
Voici un exemple :
Image utilisateur
L'icône de mon programme est l'icône d'Opera de Gtk+


Voyons comment faire ceci :
Code : Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# -*- coding:Utf-8 -*-
import pygtk
pygtk.require("2.0")
import gtk

def afficheCacheFenetre(widget, fenetre):
	[...]

def afficheMenu(widget, bouton, temps):
	[...]

fenetre = gtk.Window(gtk.WINDOW_TOPLEVEL)
fenetre.set_title("Les boîtes de dialogue")
fenetre.set_default_size(640, 480)
fenetre.set_position(gtk.WIN_POS_CENTER)
fenetre.connect("destroy", gtk.main_quit)

Premièrement, on importe les modules et on crée deux fonctions (qu'on verra plus tard). Puis, on crée une fenêtre.

Après, on crée notre icône qui ira dans la barre des tâches :
Code : Python
1
2
3
4
5
icone = gtk.StatusIcon() #Création d'une icône qui va dans la barre des tâches
icone.set_from_file("gtk.png") #Charger une image pour l'icône à partir d'un fichier
icone.set_tooltip("Gtk+") #Afficher du texte lorsque l'on pointe la souris longtemps sur l'icône
icone.connect("activate", afficheCacheFenetre, fenetre) #Lorsqu'on clique avec le bouton gauche
icone.connect("popup-menu", afficheMenu) #Lorsqu'on clique avec le bouton droit

À la première ligne, on crée cette icône.
À la deuxième, on charge dans cette icône une image avec la méthode set_from_file(filename). Il existe également la méthode set_from_stock(stock_id) qui la charge à partir d'un Stock Item.
À la troisième, on donne à cette icône un infobulle (donc du texte sera affiché au survol de la souris).
À la quatrième, on connecte l'icône à la fonction afficheCacheFenetre lorsque l'on active l'icône (donc lorsque l'on clique dessus). Dans cette méthode, on affichera ou cachera la fenêtre selon le cas.
À la cinquième ligne, on connecte l'icône à la fonction afficheMenu lorsque l'on fait un clique-droit sur cette icône. Cette fonction affichera un (popup) menu.

Ensuite, on affiche tout et on démarre la boucle principale :
Code : Python
1
2
3
fenetre.show_all()

gtk.main()


Voyons maintenant les deux fonctions que nous avons passés au début. Voici la première :
Code : Python
1
2
3
4
5
6
def afficheCacheFenetre(widget, fenetre):
	if fenetre.get_property("visible"): #Si la fenêtre est affichée
		fenetre.hide() #On la cache
	else:
		fenetre.show() #On l'affiche
		fenetre.deiconify() #Remet la fenêtre au premier plan

Au début, on vérifie si la fenêtre est affichée ; si c'est le cas, on la cache, sinon on l'affiche et on la remet au premier plan.
Donc, lorsque l'on clique(-gauche) sur l'icône dans la barre des tâches, grâce à cette fonction, on cache ou affiche la fenêtre selon le cas.

Voici la seconde fonction, qui affiche un popup menu :
Code : Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def afficheMenu(widget, bouton, temps):
	menu = gtk.Menu()

	objetMenuOuvrir = gtk.ImageMenuItem(gtk.STOCK_OPEN)
	objetMenuEnregistrer = gtk.ImageMenuItem(gtk.STOCK_SAVE)
	objetMenuQuitter = gtk.ImageMenuItem(gtk.STOCK_QUIT)
	objetMenuQuitter.connect("activate", gtk.main_quit)

	menu.append(objetMenuOuvrir)
	menu.append(objetMenuEnregistrer)
	menu.append(objetMenuQuitter)
	
	menu.show_all() #Il faut afficher le menu, car c'est un menu popup
	
	menu.popup(None, None, None, bouton, temps) #Popup le menu

Je viens de me rappeler que je ne vous ai pas montrer comment créer un menu avec du code python. Je n'ai guère le choix maintenant. Souvenez-vous, ce popup menu s'affiche lorsque l'on clique-droit sur l'icône.
À la deuxième ligne, on crée un menu déroulant.
À la quatrième ligne, on crée un élément pour le menu déroulant.
Pareil pour les lignes 5 et 6.
À la ligne 7, on connecte l'élément quitter à la méthode gtk.main_quit() (pour fermer le programme).
Aux lignes 9, 10 et 11, on ajoute ces éléments au menu déroulant.
À la ligne 13, on affiche tous les éléments du menu.
À la ligne 15, on popup le menu (on l'affiche). Les deux premiers paramètres sont inutiles pour un popup menu comme ceci (ce sont ces parents). Le troisième est une fonction qui positionnera le menu. Comme on veut que le menu apparaisse près de l'icône, on ne met rien. Les deux paramètres suivants sont les mêmes que l'on a reçu en appelant la fonction.

Désactiver un widget


Pour désactiver un widget, il suffit d'utiliser la méthode set_sensitive(sensitive). Si sensitive vaut False, le widget sera désactivé.
À quoi ressemble un widget désactivé ?

Un widget désactivé est un widget qui n'est pas/plus utilisable par l'utilisateur. Par conséquent, il sera donc gris :
Image utilisateur

Q.C.M.

Que dois-je préciser si je veux créer une image à partir d'un Stock Item ?
Quelle est la différence entre un gtk.Frame() et un gtk.AspectFrame() ?
Quelle méthode donne le pourcentage d'une barre de progression ?
Un gtk.VolumeButton() fait apparaître ...
À quoi sert gobject.idle_add() ?

Statistiques de réponses au QCM

Ce sont des widgets relativement simples que vous venez de voir. Par contre, dans le prochain chapitre, ils seront plus complexes !
Préparez-vous mentalement >_<
Et le chapitre suivant sera un TP qui devrait vous intéresser !
Chapitre précédent Sommaire

Partager

Il n'y a pas encore de commentaire pour ce tuto.

Ce tutoriel a été corrigé par les zCorrecteurs.