(site sans réclame)
Python  –  Manuel  –  Cont@ct  –  S'abonner

Module graphique Tkinter pour Python

Tkinter est le module graphique de base du langage python. Ce n'est pas le seul, par exemple, wxPython, PyQt ou PyGTK. Les exemples ci-dessous sont fonctionnels sur Debian.

1. Utilisation du module 'Tkinter'

Tout d'abord, le module Tk pour python doit être installé. Pour Debian-Lenny: apt-get install python-tk

1.1 Charger le module

Pour utiliser le module Tkinter, il faut d'abord choisir un mode de chargement:

import Tkinter charge tout le module, dont le nom doit précéder toute fonction: racine=Tkinter.Tk().

import Tkinter as tk permet d'utiliser un alias: racine=tk.Tk()

from Tkinter import * permet d'utiliser toutes les fonctions sans préciser le nom du module: racine=Tk()

Dans cette page, par souci de clarté, le module Tkinter sera toujours explicite et les variables seront en français et en minuscules.

1.2 Ouvrir une fenêtre

L'utilisation d'une fenêtre se résume schématiquement à cette procédure (les majuscules sont toujours importantes):

#! /usr/bin/python
import Tkinter
racine=Tkinter.Tk()
racine.geometry("400x300")

racine.mainloop()

Tk() permet de désigner un premier objet (une fenêtre) duquel les autres dépendront, son nom est ici 'racine'. racine.mainloop() lancera le gestionnaire d'événements. Les fonctions graphiques doivent se situer entre les deux. racine.geometry("400x300") permet de préciser la taille de la fenêtre.

1.3 Lancer le script

Tous les exemples proposés sont fonctionnels. Pour qu'ils puissent fonctionner sur UNIX, ne pas oublier #! /usr/bin/python sur la première ligne (s'assurer que le logiciel python se situe bien à cette adresse), sauvegarder le script et le rendre exécutable, par exemple avec chmod 755 votre-fichier.py.

Avec un système UNIX bien configuré, un double-clic sur l'icone peut lancer un script "graphique", mais il est préférable, lors du développement, de le lancer dans une console: ./nom-du-script.py afin de voir les éventuels messages d'erreur.

2 Les widgets simples

'widget' signifie 'bidule'. Il s'agit d'éléments simples, comme un titre, un bouton, un texte, un champ éditable... ou plus complexes, comme un système de menus.

2.1 'Label'

'Label' permet un affichage simple de texte:

import Tkinter
racine=Tkinter.Tk()
texte=Tkinter.Label(racine, text="Premier texte\ndans une fenetre", fg="black")
texte.pack(side=Tkinter.RIGHT)
racine.mainloop()

side=Tkinter.RIGHT permet de placer la chaîne de caractère à droite de la fenêtre
Label peut également recevoir une image sous format .gif:

import Tkinter
racine=Tkinter.Tk()
dessin=Tkinter.PhotoImage(file="nomdefichier.gif")
label=Tkinter.Label(image=dessin)
label.pack()
racine.mainloop()

2.2 'Text'

'Text' définit une plage permettant l'insertion et la manipulation d'un texte.

import Tkinter
racine=Tkinter.Tk()
texte=Tkinter.Text(racine, width=25, height=5)
texte.insert(Tkinter.END,'Un texte ins\xe9r\xe9')
texte.pack(side=Tkinter.RIGHT)
racine.mainloop()

'width' est la largeur de la plage en nombre de caractères, 'height' le nombre de lignes.
RIGHT concerne la plage de texte: en agrandissant la fenêtre, on verra que la plage se situe à droite, même si le texte est aligné à gauche. RIGHT est une variable du module, il faut donc la précéder du nom de celui-ci avec le mode d'importation du module qu'on a choisi.

2.3 'Entry'

'Entry' permet de saisir un texte. Il faut donc prévoir une variable permettant de recevoir le texte saisi.


import Tkinter
racine=Tkinter.Tk()
texte=Tkinter.Label(racine, text='Cliquer et saisir:', width=20, height=3, fg="black")
texte.pack()
saisir=Tkinter.StringVar() # prevoir la variable pour recevoir le texte saisi
saisie=Tkinter.Entry(textvariable=saisir, width=30)
saisie.pack()
racine.mainloop()
print saisir.get() # on recupere et affiche le texte saisi

On peut recevoir une variable numérique avec IntVar().

2.4 'Button'

'Button' définit un bouton cliquable

import Tkinter
racine=Tkinter.Tk()
bouton=Tkinter.Button(racine, text="Quitter", command=racine.quit)
bouton.pack(side=Tkinter.BOTTOM)
racine.mainloop()

side peut également prendre les valeurs LEFT, RIGHT, TOP ou CENTER

2.5 'Checkbutton'

'Chekbutton' est une "case à cocher". Une méthode est proposée pour récupérer l'information sur l'état de la "case à cocher".

import Tkinter
racine=Tkinter.Tk()
retour=Tkinter.IntVar() # on cree une variable pour l'etat de la case a cocher
bouton=Tkinter.Checkbutton(racine, variable=retour, text="Cochez-moi")
bouton.pack()
racine.mainloop()
# la valeur est recuperee lors de la sortie de la fenetre:
if retour.get() == 0: # la variable 'retour' reste a 0 si la case est restee intacte
  print "Vide!"
else:
  print "Tilt!"

2.6 'Radiobutton'

RadioButton est un ensemble de Checkbutton exclusifs pour une même variable. La variable option rendra la valeur proposée par 'value' du bouton sélectionné.

import Tkinter
racine=Tkinter.Tk()
retour=Tkinter.IntVar() # on cree une variable pour la valeur liee a la case cochee
bouton1=Tkinter.Radiobutton(racine,text="Oui", variable=retour, value=2)
bouton2=Tkinter.Radiobutton(racine,text="Non", variable=retour, value=3)
bouton3=Tkinter.Radiobutton(racine,text="P-\xea", variable=retour, value=7)
bouton1.grid()
bouton2.grid()
bouton3.grid()
racine.mainloop()
print retour.get() # retourne 2, 3 ou 7 selon le bouton choisi, ou 0 si pas de choix

Il est possible de définir des valeurs-retours sous forme de chaîne (value="bof") et en précisant retour=Tkinter.StringVar()

3 L'espace graphique Canvas

Canvas crée une surface sur laquelle on peut placer des éléments graphiques:

import Tkinter
racine=Tkinter.Tk()
fond=Tkinter.Canvas(racine, width=300, height=200, background='darkgray')
fond.pack()
 ... # votre script
racine.mainloop()

Pour les fonctions qui suivent, 'fill' permet la définition d'une couleur (même pour 'creat_text'), 'width' l'épaisseur, 'outline' la couleur du bord; les objets seront placés par "anchor".

3.1 Affichier une image

Manière d'insérer une image .gif:

import Tkinter
racine=Tkinter.Tk()
photo=Tkinter.PhotoImage(file="votre-image.gif") # ouverture de l'image
largeur=photo.width(); hauteur=photo.height() # determination des dimensions
racine.geometry(str(largeur+2)+'x'+str(hauteur+2))
racine.title(str(largeur)+'x'+str(hauteur))
fond=Tkinter.Canvas(racine, bg='black')
fond.pack()
img=fond.create_image(largeur/2+1,hauteur/2+1,image=photo)
racine.mainloop()

3.2 Rectangle, ellipse et quartier

Pour fond représentant l'ouverture d'un canevas:

rect=fond.create_rectangle(140,40,280,90, fill='white', outline='red', width=10)
ellipse=fond.create_oval(30,120,150,180, fill='green', outline='blue', width=5)
fond.create_arc(x1,y1,x2,y2,start=depart,extent=extension,style=Tkinter.PIESLICE)

Les deux premiers entiers représentent les coordonnées du point en haut à gauche du rectangle, les deux suivants celles du point en bas à droite. Pour 'create_oval' et 'create_arc', il s'agit des coordonnées du rectangle circonscrit.

Pour 'create_arc', l'angle de départ et l'extension sont donnés en degrés (progression anti-horaire). Tkinter.CHORD limite la surface entre la partie d'arc et sa corde.

3.3 Lignes et points

Avec fond représentant l'ouverture d'un canevas:

ligne=fond.create_line(160,190, 250,110, 270,170, 180,120)

Les arguments commencent par des paires qui sont des coordonnées de points.

smooth=True si une ligne brisée doit être courbée (spline)
splinesteps=12 pour un lissage de la courbe si smooth=True

capstyle=Tkinter.BUTT , ROUND ou PROJECTING
arrow=Tkinter.BOTH place une flèche aux bouts de la ligne (Tkinter.FIRST pour le départ, Tkinter.LAST pour la fin)
arrowshape=(8,10,3) permet de modifier la longueur de la flèche, la longueur des branches et la largeur.

Pour afficher le point x,y, il faut afficher une ligne qui va de x,y à x+1,y+1 (le dernier point d'une ligne n'est pas affiché).

3.4 Polygones

Pour fond représentant l'ouverture d'un canevas:

polygone=fond.create_polygon(35,105, 120,85, 95,25, 80,75, 25,60, 65,30, fill="cyan", width=5, outline='black')

Les arguments commencent par des paires qui sont des coordonnées de points. Il n'est pas nécessaire de répéter les coordonnées du premier sommet.

smooth=True si le pourtour doit être arrondi
splinesteps=12 pour un lissage de la courbe si smooth=True

3.5 Texte graphique

Pour positionner un texte au pixel près sur un canevas:

txt=fond.create_text(15, 25, text="Spam?", font="Arial 16 italic", fill="gray")

Rappel: la couleur du texte est définie ici par 'fill'!

3.6 Reconfigurer un objet

L'instance récupérée lors de la création a une importance, car elle permet de manipuler les objets créés:

fond.itemconfigure(ellipse,fill="green") # l'objet 'ellipse' est (re)colore en vert
fond.delete(rectangle1) # detruit un objet appele 'rectangle1'

Exemple (changement de couleur lié au clic sur un bouton):

#! /usr/bin/python
import Tkinter
racine=Tkinter.Tk()

fond=Tkinter.Canvas(racine, width=300, height=200, background='darkgray')
fond.pack()
rectangle=fond.create_rectangle(50,50,250,150, fill='blue')

def Rougit():
  fond.itemconfigure(rectangle,fill='red')

bouton=Tkinter.Button(racine,text="Rouge!", command=Rougit) # fonction sans guillemets!
bouton.pack()
racine.mainloop()

4. Fenêtres, cadres et panneaux

4.1 'TopLevel'

TopLevel permet l'ouverture d'une nouvelle fenêtre. Afin de ne pas surcharger l'exemple, la nouvelle fenêtre n'affiche rien de plus que la première.

import Tkinter
racine=Tkinter.Tk()
racine.title("Principale")
fenetre=Tkinter.Toplevel()
fenetre.title("Seconde")
fenetre.grid()
racine.mainloop()

Deux fenêtres vont s'ouvrir: la principale, nommée pour l'occasion 'Principale', et la seconde, appelée 'Seconde'. On subordonne le plus souvent la création d'une seconde fenêtre à un événement de la première, par exemple associée au clic d'un bouton.

4.2 'Frame' et 'LabelFrame'

Frame est un cadre, permettant de regrouper géographiquement les widgets dans une fenêtre.

import Tkinter
racine=Tkinter.Tk()
Cadre=Tkinter.Frame(racine)
bouton1=Tkinter.Button(Cadre,text="Bouton 1")
bouton2=Tkinter.Button(Cadre,text="Bouton 2")
bouton3=Tkinter.Button(Cadre,text="Bouton 3")
bouton1.pack(side=Tkinter.LEFT)
bouton2.pack(side=Tkinter.TOP)
bouton3.pack()
Cadre.pack()
racine.mainloop()

Il est possible de donner un bord et un nom à un cadre avec LabelFrame:
Cadre=Tkinter.LabelFrame(racine,text="Titre de cadre")

4.3 'PanedWindow'

PanedWindow permet de diviser une fenêtre en plusieurs panneaux adaptables.

import Tkinter
racine=Tkinter.Tk()
racine.geometry("400x300")
division=Tkinter.PanedWindow(orient=Tkinter.VERTICAL)
division.pack(expand="yes",fill="both")
panneau1=Tkinter.Label(division,text="Panneau Un")
division.add(panneau1)
panneau2=Tkinter.Label(division,text="Panneau Deux")
division.add(panneau2)
panneau3=Tkinter.Label(division,text="Panneau Trois")
division.add(panneau3)
racine.mainloop()

On adapte cette fonction dans l'autre direction avec les paramètres suivants: orient=Tkinter.HORIZONTAL.

Il est possible de créer des subdivisions dans un des panneaux. Dans l'exemple suivant, c'est le panneau 'bas' qui devient l'objet à diviser par PanedWindows: c'est donc à lui que les sous-panneaux 'gauche' et 'droite' doivent se référer.

import Tkinter
racine=Tkinter.Tk()
racine.geometry("400x300")
division=Tkinter.PanedWindow(orient=Tkinter.VERTICAL)
division.pack(expand="yes",fill="both")
haut=Tkinter.Label(division,text="Panneau du haut")
division.add(haut)
milieu=Tkinter.Label(division,text="Panneau du milieu")
division.add(milieu)
bas=Tkinter.PanedWindow(orient=Tkinter.HORIZONTAL) # nouvelle division
bas.pack(expand="yes",fill="both")
gauche=Tkinter.Label(bas,text="Panneau bas-gauche")
bas.add(gauche)
droit=Tkinter.Label(bas,text="Panneau bas-droit")
bas.add(droit)
division.add(bas) # on acheve la déclaration du panneau bas
racine.mainloop()

5.1 'Listbox'

import Tkinter
racine=Tkinter.Tk()import Tkinter
liste=Tkinter.Listbox(racine,width=10)
liste.pack()
texte=Tkinter.Text(racine,width=10)
texte.pack()
for element in ["Monthy", "Python", "Flying", "Circus"]:
  liste.insert(Tkinter.END, element)
def clic(inutile):
  texte.insert(Tkinter.END,liste.get(liste.curselection())+"\n")
liste.bind('<Double-1>', clic)
racine.mainloop()

'inutile' est une variable nécessaire mais qu'on n'utilise pas.
liste=Tkinter.Listbox(selectmode=Tkinter.EXTENDED) permet un mode de sélection multiple avec Ctrl-Clic, Maj-Clic... MULTIPLE permet une sélection multiple par ajout de simple clic.

Il est possible de remplacer le double-clic par un bouton.

#! /usr/bin/python
import Tkinter
racine=Tkinter.Tk()
liste=Tkinter.Listbox(racine,width=10)
liste.pack()
bouton=Tkinter.Button(racine,text='Confirmer')
bouton.pack()
texte=Tkinter.Text(racine,width=10)
texte.pack()
for element in ["Monthy", "Python", "Flying", "Circus"]:
  liste.insert(Tkinter.END, element)
def clic(inutile):
  texte.insert(Tkinter.END,liste.get(liste.curselection())+"\n")
bouton.bind('<Button-1>', clic)
racine.mainloop()

5.2 'Scrollbar'

'Scrollbar' permet de placer un ascenseur, afin de manipuler plus facilement une 'Listbox'. L'exemple ci-dessous montre qu'il est possible de prévoir un défilement vertical à partir d'un ascenseur horizontal.

import Tkinter
racine = Tkinter.Tk()
ascenseur= Tkinter.Scrollbar(racine,orient=Tkinter.HORIZONTAL)
ascenseur.pack(side=Tkinter.TOP,fill=Tkinter.X)
liste= Tkinter.Listbox(racine, yscrollcommand=ascenseur.set)
for i in range(0,128):
  liste.insert(Tkinter.END, str(i))
liste.pack(fill=Tkinter.Y)
ascenseur.config(command=liste.yview)
racine.mainloop()

orient=Tkinter.HORIZONTAL pour un ascenseur horizontal (vertical par défaut), même si la commande a une action verticale: 'yview'
fill=Tkinter.X met de l'espace entre les deux flèches de l'ascenseur horizontal
side=Tkinter.LEFT aurait placé l'ascenseur à gauche

5.3 'Menu'

Voici un exemple commenté d'un système de menu fonctionnel comportant des cascades (sous-menus). Pour la fonction Menu, deux méthodes sont nécessaires: add_cascade pour ajouter un menu ou un sous-menu, et add_command pour décider de la commande associée au clic. Les actions sont ici limitées à l'affichage d'un texte.

import Tkinter
racine=Tkinter.Tk()

texte=Tkinter.Text(racine) # prevoit une place pour l'affichage des textes
texte.pack()

def ecran(var): # fonction servant a l'affichage des textes:
  texte.insert(Tkinter.END,var)

sysdemenu = Tkinter.Menu(racine) # Creation du systeme de menu (variable explicite sysdemenu):

menu1 = Tkinter.Menu(sysdemenu) # Creation du premier menu:
sysdemenu.add_cascade(label="Menu 1", menu=menu1)

# addition des deux items pour le premier menu et leur commande associee
menu1.add_command(label="Cr\xe9dit", command=lambda: ecran('Cr\xe9dit: www.jchr.be\n'))
menu1.add_command(label="Quitter", command=racine.quit)

menu2 = Tkinter.Menu(sysdemenu) # Creation du second menu
sysdemenu.add_cascade(label="Menu 2", menu=menu2)

# addition du premier item pour le second menu et leur sous-items associes
item1 = Tkinter.Menu(menu2)
menu2.add_cascade(label="Item 1", menu=item1)

# addition des sous-items du premier item du second menu et leur commande associee
item1.add_command(label="Action 1", command=lambda: ecran('Item 1 / Action 1\n'))
item1.add_command(label="Action 2", command=lambda: ecran('Item 1 / Action 2\n'))

item2 = Tkinter.Menu(menu2) # addition du second item pour le second menu et leur sous-items associes
menu2.add_cascade(label="Item 2", menu=item2)

# addition des sous-items du second item du second menu et leur commande associee
item2.add_command(label="Action 1", command=lambda: ecran('Item 2 / Action 1\n'))
item2.add_command(label="Action 2", command=lambda: ecran('Item 2 / Action 2\n'))
item2.add_command(label="Action 3", command=lambda: ecran('Item 2 / Action 3\n'))
racine.config(menu=sysdemenu)
racine.mainloop()

Chaque menu commence par une ligne discontinue. Un clic transfère le menu dans une fenêtre indépendante. On peut empêcher cela en ajoutant le paramètre tearoff=0 dans la fonction 'Menu'

7. Styles

7.1 Couleurs

Pour les paramètres foreground, fg, background, bg, fill, outline

On utilise la forme "#RRGGBB" où les lettres représentent le rouge, le vert et le bleu en chiffres hexadécimaux (de '0' à '9' puis de 'a' à 'f'). Il existe aussi des noms parmi lesquels:

black, dark-gray, gray, light-gray, white
cyan, blue, violet, magenta, red, yellow, green
gold, pink, orange

7.2 Alignements

Pour side (boutons) ou justify (textes)
Tkinter.LEFT, Tkinter.RIGHT, Tkinter.TOP, Tkinter.BOTTOM

Pour anchor (images):
Tkinter.N, Tkinter.S, Tkinter.E, Tkinter.W, Tkinter.NE, Tkinter.SE, Tkinter.NW, Tkinter.SW, Tkinter.CENTER

7.3 Reliefs

relief peut prendre les valeurs Tkinter.RAISED, FLAT, SUNKEN, GROOVE et RIDGE
borderwidth, bd permet de préciser la grosseur des traits

7.4 Fontes

Valable pour 'Label', 'Text' et 'create_text', il y a plusieurs manières d'imposer une fonte, une hauteur et une décoration:

font =("Helvetica", "16", "bold italic overstrike underline")
font=("-*-lucidatypewriter-medium-r-*-*-*-200-*-*-*-*-*-*")

Une autre manière est d'utiliser le module tkFont.

8. Modules associés

Les quatre librairies qui suivent permettent de définir l'option suivante:
parent= pour désigner la fenêtre parente lorsque la boîte est refermée

8.1 Boîtes à message

import tkMessageBox as Msg importe les fonctions de boîte à messages, à préfixer de Msg.

Retournent 'ok':
Msg.showinfo(title="",message="")
Msg.showwarning(title="",message="")
Msg.showerror(title="",message="")

Retournent 'yes' ou 'no':
Msg.askquestion(title="",message="")

Retournent True ou False:
Msg.askokcancel(title="",message="")
Msg.askyesno(title="",message="")
Msg.askretrycancel(title="",message="")

Il est possible de définir les choix par default=
Msg.ABORT, Msg.RETRY, Msg.IGNORE, Msg.OK, Msg.CANCEL, Msg.YES, Msg.NO

8.2 Boîtes de saisie

import tkSimpleDialog as Saisie

chaine= Saisie.askstring(title="", prompt="")
entier= Saisie.askinteger(title="", prompt="")
decimal= Saisie.askfloat(title="", prompt="")

On peut ajouter quelques options:
initialvalue= valeur de départ (chaîne, entier ou décimal)
minvalue= valeur minimale
maxvalue= valeur maximale

8.3 Sélectionneur de fichier

import tkFileDialog as Selector

descr=Selector.askopenfilename()
descr=Selector.asksaveasfilename()

(voir ici pour la manipulation du descripteur de fichier). Options:

initialdir="" répertoire
initialfile="" fichier (ignoré pour 'open')
defaultextension="" permet de définir une extension
filetypes="dsc01*" permet d'appliquer un filtre, "*" par défaut.

8.4 Choisir une couleur

((rouge,vert,bleu),couleur)=tkColorChooser.askcolor() fait apparaître un sélectionneur de couleur. Le sous-n-uple définit trois variables (de 0 à 255) pour les couleurs fondamentales, couleur contiendra la couleur au format #RRVVBB

Il est possible de recueillir la couleur en une seule variable:

#! /usr/bin/python

import tkColorChooser
couleur=tkColorChooser.askcolor()
print couleur[0][0] # est la quantite de rouge
print couleur[0][1] # est la quantite de vert
print couleur[0][2] # est la quantite de bleu
print couleur[1]    # est la couleur sous forme #RRVVBB

askcolor() admet comme paramètres initialcolor=(rouge,vert,bleu) (trois nombres <256) pour une couleur préalablement définie et title="" pour définir un titre de boîte.

9. Documentation

9.1 Documentation dans le logiciel python

Dans le mode interactif (obtenu en saisissant python dans une console):

  >>> print dir() liste les modules chargés
  >>> print Tkinter.__file__ renvoie la localisation de Tkinter sur le système
  >>> print dir(Tkinter) liste les instructions du module Tkinter
  >>> print Tkinter.fct.__doc__ documente l'instruction précisée de Tkinter

La commande help informe sur une fonction d'un module importé:

  >>> import Tkinter
  >>> help(Tkinter.Button)

9.2 Documentation sur votre système GNU+Linux

Si python est installé, saisir man python dans une console renseigne sur les différentes manières de lancer python.

Le script /usr/bin/pydoc permet la consultation d'information de fonctions, modules, mots-clés:
pydoc -g lance une interface graphique pour une navigation dans le système d'aide

/usr/share/doc/python (adresse pouvant varier selon la distribution) contient quelques fichiers d'aide

9.3 Documentation sur Internet (anglais)

9.4 Documentation sur papier