16 - GUI (ouverture)
Ouverture hors programme. Les interfaces graphiques ne sont pas au programme de NSI, mais elles rendent les projets plus attrayants. Cette fiche présente trois bibliothèques :
tkinter, fournie avec Python,pygamepour les jeux etstreamlitpour les applications web. Les deux dernières s’installent avecpip install pygameetpip install streamlit.
Une interface graphique (GUI, graphical user interface) se programme toujours de la même façon : on crée une fenêtre et ses composants (boutons, champs de saisie, textes), on associe des fonctions aux actions de l’utilisateur, puis on lance une boucle d’événements qui attend ces actions.
Tkinter
Tkinter, exemple 1 : saisie et affichage
L’exemple suivant crée une fenêtre avec un texte, un champ de saisie et un bouton. La fonction afficher est appelée quand on valide la saisie avec la touche Entrée.
import tkinter as tk
def afficher(event):
"""Affiche un message de bienvenue avec le prénom saisi."""
accueil.configure(text="Bonjour " + champ.get() + " !")
# Fenêtre principale
fenetre = tk.Tk()
fenetre.title("Ma première fenêtre")
fenetre.minsize(width=300, height=80)
# Un texte, un champ de saisie et un bouton, empilés dans l'ordre
consigne = tk.Label(fenetre, text="Entrez votre prénom puis validez :")
consigne.pack()
champ = tk.Entry(fenetre, width=30)
champ.bind("<Return>", afficher) # touche Entrée : appel de afficher
champ.pack()
accueil = tk.Label(fenetre, text="")
accueil.pack()
bouton_quitter = tk.Button(fenetre, text="Quitter", command=fenetre.destroy)
bouton_quitter.pack()
# Boucle d'événements, interrompue quand on ferme la fenêtre
fenetre.mainloop()
Les composants de l’interface (widgets) sont placés les uns sous les autres, dans l’ordre des appels à pack(). La méthode grid() de l’exemple suivant permet de les disposer dans une grille.
Tkinter, exemple 2 : conversion Fahrenheit vers Celsius
import tkinter as tk
def convertir(event=None):
"""Convertit la température saisie, en degrés Fahrenheit, en degrés Celsius."""
fahrenheit = float(temperature.get())
celsius = 5 / 9 * (fahrenheit - 32)
resultat.config(text=f"{celsius:.2f} °C")
fenetre = tk.Tk()
fenetre.title("Conversion de Fahrenheit en Celsius")
consigne = tk.Label(fenetre, text="Température en degrés Fahrenheit :")
temperature = tk.Entry(fenetre)
temperature.bind("<Return>", convertir)
resultat = tk.Label(fenetre, text="")
bouton_convertir = tk.Button(fenetre, text="Convertir", command=convertir)
bouton_quitter = tk.Button(fenetre, text="Quitter", command=fenetre.destroy)
# Disposition en grille : ligne (row) et colonne (column)
consigne.grid(row=0, column=0, sticky="w", padx=5, pady=5)
temperature.grid(row=0, column=1, padx=5, pady=5)
bouton_convertir.grid(row=1, column=1, padx=5, pady=5)
resultat.grid(row=1, column=0, sticky="w", padx=5, pady=5)
bouton_quitter.grid(row=2, column=1, padx=5, pady=5)
fenetre.mainloop()
Le paramètre event=None permet d’appeler convertir aussi bien depuis le bouton (sans argument) que depuis la touche Entrée (avec un argument décrivant l’événement).
Pygame
Pygame dessine dans une fenêtre et gère le clavier, la souris et le temps. Un programme Pygame est une boucle qui, à chaque tour, lit les événements, met à jour l’état du jeu, dessine l’écran et attend le tour suivant.
Pygame, exemple 1 : un rectangle qui rebondit
import pygame
# Couleurs (rouge, vert, bleu)
NOIR = (0, 0, 0)
BLANC = (255, 255, 255)
ROUGE = (255, 0, 0)
pygame.init()
ecran = pygame.display.set_mode((700, 500))
pygame.display.set_caption("Rectangle qui rebondit")
horloge = pygame.time.Clock()
# Position et vitesse du rectangle (en pixels par image)
x, y = 50, 50
vitesse_x, vitesse_y = 2, 2
fini = False
while not fini:
# 1. Lecture des événements : fermeture de la fenêtre
for evenement in pygame.event.get():
if evenement.type == pygame.QUIT:
fini = True
# 2. Mise à jour : déplacement et rebond sur les bords
x = x + vitesse_x
y = y + vitesse_y
if y > 450 or y < 0:
vitesse_y = -vitesse_y
if x > 650 or x < 0:
vitesse_x = -vitesse_x
# 3. Dessin : fond, puis rectangle blanc et carré rouge à l'intérieur
ecran.fill(NOIR)
pygame.draw.rect(ecran, BLANC, [x, y, 50, 50])
pygame.draw.rect(ecran, ROUGE, [x + 10, y + 10, 30, 30])
pygame.display.flip()
# 4. Attente : au plus 60 images par seconde
horloge.tick(60)
pygame.quit()
Pygame, exemple 2 : du texte qui tourne
import pygame
NOIR = (0, 0, 0)
BLANC = (255, 255, 255)
pygame.init()
ecran = pygame.display.set_mode((400, 400))
pygame.display.set_caption("Texte en rotation")
horloge = pygame.time.Clock()
police = pygame.font.SysFont("Arial", 28, bold=True)
angle = 0
fini = False
while not fini:
for evenement in pygame.event.get():
if evenement.type == pygame.QUIT:
fini = True
ecran.fill(BLANC)
# Texte fixe, puis le même texte tourné de « angle » degrés
image = police.render("NSI", True, NOIR)
ecran.blit(image, [20, 20])
image_tournee = pygame.transform.rotate(image, angle)
rectangle = image_tournee.get_rect(center=(200, 220))
ecran.blit(image_tournee, rectangle)
angle = (angle + 1) % 360
pygame.display.flip()
horloge.tick(60)
pygame.quit()
Pour aller plus loin : le site Program Arcade Games (en anglais) propose un cours complet avec Pygame.
Streamlit
Streamlit transforme un script Python en application web : chaque appel à st.… ajoute un composant à la page. On exécute le script avec la commande streamlit run mon_fichier.py, qui ouvre l’application dans le navigateur ; le script est réexécuté à chaque action de l’utilisateur.
import streamlit as st
st.title("Convertisseur de températures")
fahrenheit = st.slider("Température en degrés Fahrenheit", -40, 120, 68)
celsius = 5 / 9 * (fahrenheit - 32)
st.write(f"{fahrenheit} °F correspondent à {celsius:.1f} °C.")
gauche, droite = st.columns(2)
if gauche.button("Eau qui gèle"):
droite.write("0 °C, soit 32 °F")
if gauche.button("Eau qui bout"):
droite.write("100 °C, soit 212 °F")
with st.expander("Comment est faite la conversion ?"):
st.write("On retire 32, puis on multiplie par 5/9.")
st.code("celsius = 5 / 9 * (fahrenheit - 32)")