POO: Programmation orientée objets
Maintenant qu'on sait ce qu'est la POO, on peut s'amuser...

Tkinter ?

Tkinter est une bibliothèque permettant de créer une interface graphique entre l'utilisateur et la machine

Installer Tkinter

Tkinter est normalement installé sinon aller dans le CMD puis pip install tkinter

Au début de votre script, vous aurez simplement à taper les lignes suivantes afin d’importer la bibliothèque tkinter :

from tkinter import *
import tkinter as tk

Maintenant que l’on a spécifié que l’on allait utiliser cette bibliothèque, on peut commencer à mettre en place notre fenêtre.

Création de la fenêtre

C’est dans cette fenêtre que tous les éléments vont apparaître.

Pour commencer, nous allons créer une fenêtre. Pour cela une ligne suffit:

fenetre = Tk()

Lorsque l’on exécute le script rien ne se passe: il faut spécifier au script que l’on veut faire apparaître la fenêtre. Pour cela, entrer la ligne suivante à la fin de votre script.

fenetre.mainloop()

Il est important que cette ligne reste la dernière de votre programme, car tout ce qui sera écrit après cette ligne n’apparaîtra pas dans la fenêtre

On obtient alors normalement le résultat suivant :

Maintenant que l’on a créé cette fenêtre, on peut la personnaliser: lui donner un nom, des dimensions, une couleur de fond etc…

fenetre.title("Ma permière fenêtre Tkinter!")
fenetre.geometry("1080x720")
fenetre.config(bg="#d1fdff")

Les dimensions seront écrites sous la forme "largeurxhauteur"

La couleur peut être spécifiée de deux manières différentes:

  • Avec le nom de la couleur en anglais (ex. bg="grey")
  • En utilisant sa notation en héxadécimal, comme dans l’exemple donné ci-dessus. Il est possible de trouver des couleurs en héxadécimal à l’aide de cet outil

On obtient alors ceci :

Il est également possible de personnaliser l’icône de la fenêtre.

Pour cela, il vous faudra une image au format .ico . On peut convertir des images au format .png en .ico à l’aide d’un convertisseur en ligne

Une fois que vous avez votre icône, placez la dans le même dossier que votre script, et entrez la ligne suivante (en remplaçant "logo.ico" par "lenomdevotreicone.ico")

fenetre.iconbitmap("logo.ico")

Il est aussi possible de définir la taille minimale de la fenêtre:

fenetre.minsize(500,500)

On a donc appris à personnaliser notre fenêtre tkinter… mais elle reste tout de même bien vide. Nous allons donc voir comment ajouter des éléments à cette fenêtre.

Ajouter du texte

Pour ajouter du texte sur notre interface, on va utiliser une instance nommée Label

titre = Label(fenetre, text="Voici un exemple de Label en police consolas et en taille 20", font=("Consolas",20), bg="#d1fdff", fg="black")
soustitre = Label(fenetre, text="Voici un exemple de Label en police Helvetica et en taille 15", font=("Helvetica",15), bg="#d1fdff", fg="black")

On remarque que l’on peut personnaliser différents aspects du Label:

  • La boîte dans laquelle il se trouve (cette notion sera abordée un peu plus loin)
  • Le texte qu’il renferme ( text )
  • Sa police et taille d’écriture ( font )
  • Son arrière plan ( bg pour background )
  • Sa couleur de police ( fg pour foreground )

Si l’on exécute le script, on s’aperçoit que le texte ne s’affiche pas: là aussi, il faut spécifier qu’il faut l’afficher à l’aide de l’instruction .pack(). Il sera nécessaire d’appeler tout nouvel élément que l’on créé de cette manière.

titre.pack()
soustitre.pack()

Les différents éléments que vous allez incorporer à votre fenêtre apparaîtront dans l’ordre dans lequel vous allez les appeler à l’aide de .pack() , ici, titre sera donc au dessus de soustitre.

Il est possible de donner une marge à notre texte en utilisant pady et padx. Par exemple, l’instruction suivante donne une marge de 45 des deux côtés en hauteur

titre.pack(pady=45)

On peut aussi spécifier au texte de prendre toute la place possible en utilisant expand comme ceci:

titre.pack(expand=YES)

Ajouter des boutons

Maintenant que l’on sait faire apparaître du texte sur notre fenêtre, on va s’intéresser aux boutons. Leur mise en place est très similaire à celle des Labels. Cependant, on peut leur ajouter d’autres arguments

  • command qui spécifiera la fonction à éxécuter en cas de clic sur le bouton
  • width et height qui permettent de modifier respectivement sa largeur et sa longueur. Si ils ne sont pas spécifiés, la taille du bouton sera celle nécessaire pour que son texte s’affiche
nb_clicks=0
def compteur():
global nb_clicks
nb_clicks += 1
print(nb_clicks)

bouton1 = Button(fenetre, text="Je suis un bouton", font=("Consolas",15), bg="white", fg="black", command=compteur, width=10, height=3)

Ici, on a donc créé un Bouton d’une largeur de 10 et d’un hauteur de 3 qui incrémente un compteur à chaque clic et qui donne la valeur du compteur dans la console

Mais il est où mon boutton🤪

Mais ce que l’on chercherait à faire, ce serait de faire apparaître le texte directement dans la fenêtre.

On créé alors un nouveau Label qui va afficher la valeur de nb_clicks.

nb_clicks=0

textecompteur = Label(fenetre, text="nombre de clicks : %s" %(nb_clicks), font=("Helvetica",15), bg="#d1fdff", fg="black")
#ici, dans la chaîne de caractères, le "%s" sera remplacé par la valeur de la variable placée dans le tuple situé après le % soit nb_clicks

def compteur():
global nb_clicks
nb_clicks += 1
print(nb_clicks)

bouton1 = Button(fenetre, text="Je suis un bouton", font=("Consolas",15), bg="white", fg="black", command=compteur, width=50, height=3)

On se rend alors compte que même si la valeur est incrémentée, le label ne s’actualise pas dans la fenêtre. On va alors ajouter une ligne dans la fonction compteur qui va mettre à jour ce Label à chaque clic du bouton à l’aide de l’instruction .config()

def compteur():
global nb_clicks
nb_clicks += 1
textecompteur.config(text="nombre de clicks : %s" %(nb_clicks))

Voici ce que ça donne:

Cependant, si la fonction à exécuter nécessite des arguments, les choses vont se passer un peu différemment.

Dans cet exemple, on va créer deux boutons, qui vont exécuter la même fonction en cas de clic, mais avec des arguments différents.

Il est nécessaire pour cela d’importer la fonction partial de la library functools.

from functools import partial

On créé d’abord notre fonction. Ici, elle prend en argument une couleur et applique cette couleur au Label titre en cas d’appel de la fonction:

def changer_couleur_titre(couleur):
titre.config(fg=couleur)

Ensuite, on créé les boutons avec pour commande partial( nomdelafonction, argument )

bouton2 = Button(fenetre, text="titre rouge", font=("Consolas",15), bg="white", fg="black", command=partial(changer_couleur_titre,"red"))
bouton3 = Button(fenetre, text="titre bleu", font=("Consolas",15), bg="white", fg="black", command=partial(changer_couleur_titre,"blue"))

Lorsque l’on va cliquer sur bouton2 le titre va devenir rouge, et sur le bouton3 il deviendra bleu

Ajouter un champ pour entrer du texte

Pour certains programmes, et en particulier les simulateurs, il est nécessaire d’entrer des données manuellement, et c’est là que les Entry entrent en jeu.

Là aussi, le processus est assez similaire aux Labels, la seule différence est que text est remplacé par textvariable qui sera donc la variable que l’on va modifier lorsque l’on écrira dans ce champ.

A l’instar des boutons, il est aussi possible de modifier leur taille à l’aide de width et height

Ici, la création de la variable est un peu différente car il doit s’agir d’une variable tkinter. On procède alors de la manière suivante:

#création de la variable
variable = tk.StringVar()
variable.set("Vous pouvez me modifier")

#création du champ
entree = Entry(fenetre, textvariable=variable, font=("Helvetica",15), bg="#d1fdff", fg="black", width=30)

Il faudra utiliser la même méthode à chaque fois que l’on voudra créer des variables pour des chaînes de caractères que l’on voudra afficher dans une interface tkinter

Il est possible aussi possible d’appeler cette variable (en utilisant .get() car il s’agit d’une variable tkinter) pour modifier du texte par exemple:

def changer_titre():
titre.config(text=variable.get())

bouton4 = Button(fenetre, text="Cliquez pour actualiser", font=("Helvetica",15), bg="#d1fdff", fg="black", command = changer_titre)

Ici, à chaque clic du bouton, le texte du titre sera actualisé pour devenir celui du champ:

Maintenant que l’on sait incorporer différents éléments à notre fenêtre, on va s’intéresser à comment les organiser

Utiliser les boites

Les boites, ou Frames, sont très utiles lorsque l’on utilise tkinter puisqu’elles permettent de regrouper des éléments entre eux et ainsi créer différents menus entre lesquels on peut naviguer.

Il est nécessaire de les définir avant les éléments qui vont en faire partie, c’est pourquoi il est conseillé de les définir juste en dessous de la configuration de la fenêtre.

On créé une boite de la manière suivante, en spécifiant la boite dans laquelle elle est placée, et la couleur de son arrière plan

boitelabels = Frame(fenetre, bg="#d1fdff")

Ici, on a spécifié que la boite apparaîtrait dans la fenêtre principale, mais il est aussi possible de faire apparaître des boites dans des boites.

Comme tout autre élément, si l’on veut qu’une boite apparaisse, il ne faudra pas oublier de l’appeler avec un .pack(). Si un élément est appelé ainsi mais pas sa boîte, il n’apparaîtra pas, et si jamais il n’est pas appelé et que sa boite si, il n’apparaîtra pas non plus

Pour qu’un élément apparaisse dans une boîte, il suffit de remplacer le fenetre que l’on utilisait jusqu’à présent par le nom de la boite:

titre = Label(boitelabels, text="Voici un exemple de Label en police consolas et en taille 20", font=("Consolas",20), bg="#d1fdff", fg="black")
soustitre = Label(boitelabels, text="Voici un exemple de Label en police Helvetica et en taille 15", font=("Helvetica",15), bg="#d1fdff", fg="black")

Nous allons maintenant essayer de créer un menu nous permettant de naviguer entre tout ce que l’on a créé jusqu’à présent.

On créé alors différentes boites pour nos différents éléments. Dans cet exemple

  • boitelabels contiendra les éléments servi à la démonstration de ce que sont les Labels
  • boitecompteur contiendra le compteur créé un peu plus tôt
  • boitecouleurs contiendra les boutons permettant de modifier la couleur du titre
  • boiteentree contiendra les éléments ayant servi à la démonstration de l’utilité des Entries
  • boitemenu contiendra les boutons permettant d’afficher les différentes boites. Elle va être la seule à apparaître lorsque l’on lancera le script et permettra d’afficher les autres
boitecompteur = Frame(fenetre, bg="#d1fdff")
boitecouleurs = Frame(fenetre, bg="#d1fdff")
boiteentree = Frame(fenetre, bg="#d1fdff")
boitemenu = Frame(fenetre, bg="#d1fdff")

En on n’oublie pas de modifier la boite de chaque élément pour qu’il n’apparaisse plus dans la fenêtre principale mais dans la boite dans laquelle on veut qu’il apparaisse

#exemple: ici on place le label textecompteur dans la boitecompteur:
textecompteur = Label(boitecompteur, text="nombre de clicks : %s" %(nb_clicks), font=("Helvetica",15), bg="#d1fdff", fg="black")

On va aussi créer des boutons dans boitemenu qui, lorqu’ils seront cliqués appelleront une autre boite avec un .pack() et feront disparaître le menu à l’aide de .pack_forget(). On va aussi mettre en place des boutons de retour au menu dans chacune des autres boites qui vont, eux, faire disparaître leur boite et apparaître le menu en cas de clic;

def afficher_labels():
boitelabels.pack(expand=YES)
boitemenu.pack_forget()

def afficher_compteur():
boitecompteur.pack(expand=YES)
boitemenu.pack_forget()

def afficher_couleurs():
boitecouleurs.pack(expand=YES)
boitemenu.pack_forget()

def afficher_entree():
boiteentree.pack(expand=YES)
boitemenu.pack_forget()

def retour_menu():
boitemenu.pack(expand=YES)
boitelabels.pack_forget()
boitecompteur.pack_forget()
boitecouleurs.pack_forget()
boiteentree.pack_forget()

b_labels = Button(boitemenu, text="Afficher les Labels", font=("Consolas",15), bg="white", fg="black", command=afficher_labels, width=75)
b_compteur = Button(boitemenu, text="Afficher le compteur", font=("Consolas",15), bg="white", fg="black", command=afficher_compteur, width=75)    
b_couleurs = Button(boitemenu, text="Afficher les boutons pour changer la couleur du titre", font=("Consolas",15), bg="white", fg="black", command=afficher_couleurs, width=75)    
b_entree = Button(boitemenu, text="Afficher le champ pour changer le titre", font=("Consolas",15), bg="white", fg="black", command=afficher_entree, width=75)
b_retour1 = Button(boitelabels, text="retourner au menu", font=("Consolas",15), bg="white", fg="black", command=retour_menu, width=35)
b_retour2 = Button(boitecompteur, text="retourner au menu", font=("Consolas",15), bg="white", fg="black", command=retour_menu, width=35)
b_retour3 = Button(boitecouleurs, text="retourner au menu", font=("Consolas",15), bg="white", fg="black", command=retour_menu, width=35)
b_retour4 = Button(boiteentree, text="retourner au menu", font=("Consolas",15), bg="white", fg="black", command=retour_menu, width=35)
Le Menu

Tout ça est bien beau, mais pour l’instant on ne sait qu’afficher différents éléments les uns au dessous des autres, mais pas les uns à côté des autres. C’est là que les grilles vont intervenir

Utiliser les grilles

Pour faire une grille, on va remplacer les .pack() que l’on utilisait par des .grid(). Il faut savoir que si l’on utilise une grille pour un élément, tous les éléments présents dans la même boite devront eux aussi utiliser cette même grille.

Comme on voudrait seulement placer deux des boutons côte à côte, on va les placer dans une sous boite de la boite du menu:

#création de la sous boite
sousboitemenu = Frame(boitemenu, bg="#d1fdff")

Et on modifie la boite des deux boutons concernés, ainsi que leurs dimensions pour qu’ils soient alignés avec les autres. (On ajoute aussi un \n dans le texte du second bouton pour qu’il s’affiche sur deux lignes)

b_compteur = Button(sousboitemenu, text="Afficher le compteur", font=("Consolas",15), bg="white", fg="black", command=afficher_compteur, width=36, height=2)    
b_couleurs = Button(sousboitemenu, text="Afficher les boutons \npour changer la couleur du titre", font=("Consolas",15), bg="white", fg="black", command=afficher_couleurs, width=36, height=2) 

Il est temps maintenant de placer les boutons en grille à l’aide de .grid().

Cette méthode accepte plusieurs arguments:

  • row qui définit la ligne dans laquelle l’élément va être placé
  • column qui définit sa colonne
  • sticky qui définit de quel côté de la fenêtre l’élément doit se rapprocher ( W, E, S ou N pour les quatre points cardinaux)
  • padx et pady (optionnels) qui définissent les marges en x et en y
b_compteur.grid(row=1, column=0, sticky=W, pady=5, padx=5)
b_couleurs.grid(row=1, column=1, sticky=W, pady=5, padx=5)

On obtient alors le résultat suivant:

Conclusion

Voilà, vous possédez maintenant les bases nécessaires pour pouvoir créer vos propres interfaces graphiques pour vos scripts Python !

Vous pouvez même créer des .exe pour pouvoir l'utiliser simplement avec auto-py-to-exe par exemple😉

Vous voilà expert en POO, il est temps de réfléchir à un projet

Si vous n'avez pas d'idée, j'ai ce qu'il faut