« Programmation Python/Utilisation de fenêtres et de graphismes » : différence entre les versions

Contenu supprimé Contenu ajouté
DannyS712 (discussion | contributions)
m <source> -> <syntaxhighlight> (phab:T237267)
Ligne 15 :
Pour la suite des explications, nous supposerons bien évidemment que le module ''Tkinter'' a déjà été installé sur votre système. Pour pouvoir en utiliser les fonctionnalités dans un script Python, il faut que l'une des premières lignes de ce script contienne l'instruction d'importation :
 
<sourcesyntaxhighlight lang="Python">
from Tkinter import *
</syntaxhighlight>
</source>
 
Attention, suivant les versions de Python (a priori à partir de la version 3) l'appel du module Tkinter se fait avec un t minuscule :
 
<sourcesyntaxhighlight lang="Python">
from tkinter import *
</syntaxhighlight>
</source>
 
[[Image:Apprendre à programmer avec Python 15.png|right]]
Ligne 29 :
Comme toujours sous Python, il n'est même pas nécessaire d'écrire un script. Vous pouvez faire un grand nombre d'expériences directement à la ligne de commande, en ayant simplement lancé Python en mode interactif. Dans l'exemple qui suit, nous allons créer une fenêtre très simple, et y ajouter deux ''widgets''<ref>''widget'' est le résultat de la contraction de l'expression ''window gadget''. Dans certains environnements de programmation, on appellera cela plutôt un « contrôle » ou un « composant graphique ». Ce terme désigne en fait toute entité susceptible d'être placée dans une fenêtre d'application, comme par exemple un bouton, une case à cocher, une image, etc., et parfois aussi la fenêtre elle-même.</ref> typiques : un bout de texte (ou ''label'') et un bouton (ou ''button'').
 
<sourcesyntaxhighlight lang="Python">
>>> from Tkinter import *
>>> fen1 = Tk()
Ligne 37 :
>>> bou1.pack()
>>> fen1.mainloop()
</syntaxhighlight>
</source>
 
Note : Suivant la version de Python utilisée, vous verrez déjà apparaître la fenêtre d'application immédiatement après avoir entré la deuxième commande de cet exemple, ou bien seulement après la septième<ref>Si vous effectuez cet exercice sous ''Windows'', nous vous conseillons d'utiliser de préférence une version standard de Python dans une fenêtre DOS ou dans IDLE plutôt que ''PythonWin''. Vous pourrez mieux observer ce qui se passe après l'entrée de chaque commande.</ref>.
Ligne 137 :
Le bouton « Quitter » sert bien évidemment à terminer l'application en refermant la fenêtre.
 
<sourcesyntaxhighlight lang="python">
# Petit exercice utilisant la bibliothèque graphique Tkinter
 
Ligne 182 :
 
fen1.destroy() # destruction (fermeture) de la fenêtre
</syntaxhighlight>
</source>
 
Conformément à ce que nous avons expliqué dans le texte des pages précédentes, la fonctionnalité de ce programme est essentiellement assurée par les deux fonctions <code>drawline()</code> et <code>changecolor()</code>, qui seront activées par des événements, ceux-ci étant eux-mêmes définis dans la phase d'initialisation.
Ligne 223 :
<li>Réfléchissez !</li>
<li>
<sourcesyntaxhighlight lang="Python">
from Tkinter import *
 
Ligne 243 :
i = i +1
base.mainloop()
</syntaxhighlight>
</source>
Variante :
<sourcesyntaxhighlight lang="Python">
from Tkinter import *
 
Ligne 286 :
Button(base, text='5', command = a5).pack(side =LEFT)
base.mainloop()
</syntaxhighlight>
</source>
[[Image:Apprendre à programmer avec Python 72.png|center|Fenêtre avec les cinq anneaux olympiques]]
</li>
Ligne 302 :
|}
 
<sourcesyntaxhighlight lang="Python">
from Tkinter import *
 
Ligne 354 :
b2.pack(side =RIGHT, padx =3, pady =3)
fen.mainloop()
</syntaxhighlight>
</source>
 
Commençons par analyser le programme principal, à la fin du script :
Ligne 387 :
<li>Voir ci dessous</li>
<li>
<sourcesyntaxhighlight lang="Python">
# Dessin d'un damier, avec placement de pions au hasard
Ligne 440 :
b2.pack(side =RIGHT, padx =3, pady =3)
fen.mainloop()#
</syntaxhighlight>
</source>
</li>
</ol>
Ligne 455 :
Les langages interprétés disposent donc toujours de fonctions permettant d'évaluer une chaîne de caractères comme une suite d'instructions du langage lui-même. Il devient alors possible de construire en peu de lignes des structures de programmes très dynamiques. Dans l'exemple ci-dessous, nous utilisons la fonction intégrée <code>eval()</code> pour analyser l'expression mathématique entrée par l'utilisateur dans le champ prévu à cet effet, et nous n'avons plus ensuite qu'à afficher le résultat.
 
<sourcesyntaxhighlight lang="Python">
# Exercice utilisant la bibliothèque graphique Tkinter et le module math
 
Ligne 477 :
 
fenetre.mainloop()
</syntaxhighlight>
</source>
 
Au début du script, nous commençons par importer les modules ''Tkinter'' et ''math'', ce dernier étant nécessaire afin que la dite calculatrice puisse disposer de toutes les fonctions mathématiques et scientifiques usuelles : sinus, cosinus, racine carrée, etc.
Ligne 487 :
<code>eval()</code> fait appel à l'interpréteur pour évaluer une expression Python qui lui est transmise dans une chaîne de caractères. Le résultat de l'évaluation est fourni en retour. Exemple :
 
<sourcesyntaxhighlight lang="Python">
chaine = "(25 + 8)/3" # chaîne contenant une expression mathématique
res = eval(chaine) # évaluation de l'expression contenue dans la chaîne
print res +5 # => le contenu de la variable res est numérique
</syntaxhighlight>
</source>
 
<code>str()</code> transforme une expression numérique en chaîne de caractères. Nous devons faire appel à cette fonction parce que la précédente renvoie une valeur numérique, que nous convertissons à nouveau en chaîne de caractères pour pouvoir l'incorporer au message « Résultat = ».
Ligne 501 :
Attention, à présent : afin que ce dernier widget puisse vraiment faire son travail, c'est-à-dire transmettre au programme l'expression que l'utilisateur y aura encodée, ''nous lui associons un événement'' à l'aide de la méthode <code>bind()</code><ref>En anglais, le mot ''bind'' signifie « lier »</ref> :
 
<sourcesyntaxhighlight lang="Python">
entree.bind("<Return>",evaluer)
</syntaxhighlight>
</source>
 
Cette instruction signifie : « Lier l'événement “pression sur la touche Return” à l'objet <entree>, le gestionnaire de cet événement étant la fonction <evaluer> ».
Ligne 511 :
Profitons de l'occasion pour observer encore une fois la syntaxe des instructions destinées à mettre en œuvre une méthode associée à un objet :
 
<sourcesyntaxhighlight lang="Python">
objet.méthode(arguments)
</syntaxhighlight>
</source>
 
On écrit d'abord le nom de l'objet sur lequel on désire intervenir, puis le point (qui fait office d'opérateur), puis le nom de la méthode à mettre en œuvre ; entre les parenthèses associées à cette méthode, on indique enfin les arguments qu'on souhaite lui transmettre.
Ligne 529 :
Nous n'allons pas entrer dans trop de détails. Si vous voulez bien encoder et expérimenter le petit script ci-dessous, vous aurez vite compris le principe.
 
<sourcesyntaxhighlight lang="Python">
# Détection et positionnement d'un clic de souris dans une fenêtre :
 
Ligne 546 :
 
fen.mainloop()
</syntaxhighlight>
</source>
 
[[Image:Apprendre à programmer avec Python 23.png|200px|right]]
Ligne 650 :
Nous pourrions effectuer un certain nombre de tentatives en fournissant à la méthode <code>pack()</code> des arguments de type « side = », comme nous l'avons déjà fait précédemment, mais cela ne nous mène pas très loin. Essayons par exemple :
 
<sourcesyntaxhighlight lang="Python">
from Tkinter import *
 
Ligne 664 :
 
fen1.mainloop()
</syntaxhighlight>
</source>
 
... mais le résultat n'est pas vraiment celui que nous recherchions !!! :
Ligne 675 :
 
[[Image:Apprendre à programmer avec Python 26.png|right]]
<sourcesyntaxhighlight lang="Python">
from Tkinter import *
 
Ligne 688 :
entr2.grid(row =1, column =1)
fen1.mainloop()
</syntaxhighlight>
</source>
 
Dans ce script, nous avons donc remplacé la méthode <code>pack()</code> par la méthode <code>grid()</code>. Comme vous pouvez le constater, l'utilisation de la méthode <code>grid()</code> est très simple. Cette méthode considère la fenêtre comme un tableau (ou une grille). Il suffit alors de lui indiquer dans quelle ligne (''row'') et dans quelle colonne (''column'') de ce tableau on souhaite placer les widgets. On peut numéroter les lignes et les colonnes comme on veut, en partant de zéro, ou de un, ou encore d'un nombre quelconque : ''Tkinter'' ignorera les lignes et colonnes vides. Notez cependant que si vous ne fournissez aucun numéro pour une ligne ou une colonne, la valeur par défaut sera zéro.
Ligne 694 :
''Tkinter'' détermine automatiquement le nombre de lignes et de colonnes nécessaire. Mais ce n'est pas tout : si vous examinez en détail la petite fenêtre produite par le script ci-dessus, vous constaterez que nous n'avons pas encore tout à fait atteint le but poursuivi. Les deux chaînes apparaissant dans la partie gauche de la fenêtre sont centrées, alors que nous souhaitions les aligner l'une et l'autre par la droite. Pour obtenir ce résultat, il nous suffit d'ajouter un argument dans l'appel de la méthode <code>grid()</code> utilisée pour ces widgets. L'option <code>sticky</code> peut prendre l'une des quatre valeurs <code>N</code>, <code>S</code>, <code>W</code>, <code>E</code> (les quatre points cardinaux en anglais). En fonction de cette valeur, on obtiendra un alignement des widgets par le haut, par le bas, par la gauche ou par la droite. Remplacez donc les deux premières instructions <code>grid()</code> du script par :
 
<sourcesyntaxhighlight lang="Python">
txt1.grid(row =0, sticky =E)
txt2.grid(row =1, sticky =E)
</syntaxhighlight>
</source>
 
… et vous atteindrez enfin exactement le but recherché.
Ligne 709 :
Le code correspondant est le suivant :
 
<sourcesyntaxhighlight lang="Python">
from Tkinter import *
 
Ligne 738 :
# démarrage :
fen1.mainloop()
</syntaxhighlight>
</source>
 
Pour pouvoir faire fonctionner ce script, il vous faudra probablement remplacer le nom du fichier image (''Martin_P.gif'') par le nom d'une image de votre choix. Attention : la bibliothèque ''Tkinter'' standard n'accepte qu'un petit nombre de formats pour cette image. Choisissez de préférence le format GIF.
Ligne 770 :
Vous pouvez par exemple assez fréquemment utiliser la composition d'instructions pour appliquer la méthode de mise en page des widgets (grid(), pack() ou place()) au moment même où vous créez ces widgets. Le code correspondant devient alors un peu plus simple, et parfois plus lisible. Vous pouvez par exemple remplacer les deux lignes :
 
<sourcesyntaxhighlight lang="Python">
txt1 = Label(fen1, text ='Premier champ :')
txt1.grid(row =1, sticky =E)
</syntaxhighlight>
</source>
 
du script précédent par une seule, telle que :
 
<sourcesyntaxhighlight lang="Python">
Label(fen1, text ='Premier champ :').grid(row =1, sticky =E)
</syntaxhighlight>
</source>
 
Dans cette nouvelle écriture, vous pouvez constater que nous faisons l'économie de la variable intermédiaire <code>txt1</code>. Nous avions utilisé cette variable pour bien dégager les étapes successives de notre démarche, mais elle n'est pas toujours indispensable. Le simple fait d'invoquer la classe <code>Label()</code> provoque en effet l'instanciation d'un objet de cette classe, même si l'on ne mémorise pas la référence de cet objet dans une variable (''Tkinter'' la conserve de toute façon dans sa représentation interne de la fenêtre). Si l'on procède ainsi, la référence est perdue pour le restant du script, mais elle peut tout de même être transmise à une méthode de mise en page telle que <code>grid()</code> au moment même de l'instanciation, en une seule instruction composée. Voyons cela un peu plus en détail :
Ligne 785 :
Jusqu'à présent, nous avons créé des objets divers (par instanciation à partir d'une classe quelconque), en les affectant à chaque fois à des variables. Par exemple, lorsque nous avons écrit :
 
<sourcesyntaxhighlight lang="Python">
txt1 = Label(fen1, text ='Premier champ :')
</syntaxhighlight>
</source>
 
Nous avons créé une instance de la classe <code>Label()</code>, que nous avons assignée à la variable <code>txt1</code>.
Ligne 795 :
Lorsque ce genre de situation se présente, il est plus judicieux d'utiliser la composition d'instructions. Par exemple, on préférera le plus souvent remplacer les deux instructions :
 
<sourcesyntaxhighlight lang="Python">
somme = 45 + 72
print somme
</syntaxhighlight>
</source>
 
par une seule instruction composée, telle que :
 
<sourcesyntaxhighlight lang="Python">
print 45 + 72
</syntaxhighlight>
</source>
 
On fait ainsi l'économie d'une variable.
Ligne 814 :
Et dans ce cas, il faut obligatoirement utiliser deux instructions distinctes, l'une pour instancier le widget et l'autre pour lui appliquer ensuite la méthode de mise en page. Vous ne pouvez pas, par exemple, construire une instruction composée telle que :
 
<sourcesyntaxhighlight lang="Python">
entree = Entry(fen1).pack() # faute de programmation !!!
</syntaxhighlight>
</source>
 
En apparence, cette instruction devrait instancier un nouveau widget et l'assigner à la variable entree, la mise en page s'effectuant dans la même opération à l'aide de la méthode <code>pack()</code>.
Ligne 824 :
Pour obtenir une vraie référence du widget, vous devez utiliser deux instructions :
 
<sourcesyntaxhighlight lang="Python">
entree = Entry(fen1) # instanciation du widget
entree.pack() # application de la mise en page
</syntaxhighlight>
</source>
 
Note : Lorsque vous utilisez la méthode <code>grid()</code>, vous pouvez simplifier encore un peu votre code, en omettant l'indication de nombreux numéros de lignes et de colonnes. À partir du moment où c'est la la méthode <code>grid()</code> qui est utilisée pour positionner les widgets, ''Tkinter'' considère en effet qu'il existe forcément des lignes et des colonnes11. Si un numéro de ligne ou de colonne n'est pas indiqué, le widget correspondant est placé dans la première case vide disponible.
Ligne 833 :
Le script ci-dessous intègre les simplifications que nous venons d'expliquer :
 
<sourcesyntaxhighlight lang="Python">
from Tkinter import *
fen1 = Tk()
Ligne 858 :
# démarrage :
fen1.mainloop()
</syntaxhighlight>
</source>
 
== Modification des propriétés d'un objet - Animation ==
Ligne 866 :
Veuillez donc écrire, tester, puis analyser le script ci-dessous :
 
<sourcesyntaxhighlight lang="Python">
from Tkinter import *
 
Ligne 909 :
# démarrage du réceptionnaire d'évènements (boucle principale) :
fen1.mainloop()
</syntaxhighlight>
</source>
 
[[Image:Apprendre à programmer avec Python 28.png|center]]
Ligne 954 :
<ol>
<li>
<sourcesyntaxhighlight lang="Python">
# Simulation du phénomène de gravitation universelle
 
Ligne 1 054 :
 
fen.mainloop()
</syntaxhighlight>
</source>
[[Image:Apprendre à programmer avec Python 73.png|center|capture d'écran du résultat final]]
</li>
Ligne 1 061 :
<li>Réfléchissez !</li>
<li>
<sourcesyntaxhighlight lang="Python">
# Conversions de températures Fahrenheit <=> Celsius
 
Ligne 1 097 :
 
fen.mainloop()
</syntaxhighlight>
</source>
[[Image:Apprendre à programmer avec Python 74.png|center|capture d'écran du résultat final]]
</li>
Ligne 1 104 :
<li>Voir ci dessous.</li>
<li>
<sourcesyntaxhighlight lang="Python">
# Cercles et courbes de Lissajous
 
Ligne 1 134 :
 
fen.mainloop()
</syntaxhighlight>
</source>
[[Image:Apprendre à programmer avec Python 75.png|center|capture d'écran du résultat final]]
</li>
Ligne 1 146 :
Pour conclure cette première prise de contact avec l'interface graphique ''Tkinter'', voici un dernier exemple d'animation, qui fonctionne cette fois de manière autonome dès qu'on l'a mise en marche.
 
<sourcesyntaxhighlight lang="Python">
from Tkinter import *
 
Ligne 1 202 :
# démarrage du réceptionnaire d'évènements (boucle principale) :
fen1.mainloop()
</syntaxhighlight>
</source>
 
[[Image:Apprendre à programmer avec Python 30.png|center]]
Ligne 1 257 :
<li>Réfléchissez !</li>
<li>
<sourcesyntaxhighlight lang="Python">
 
# Chutes et rebonds
Ligne 1 308 :
 
fen.mainloop()
</syntaxhighlight>
</source>
[[Image:Apprendre à programmer avec Python 76.png|center|capture d'écran du résultat final]]
</li>