PYTHON
INTERFACES GRAPHIQUES

Objectif

Il existe de nombreuses bibliothèques pour créer des interfaces graphiques en Python :

Il s'agit ici de mettre en œuvre Tkinter, une solution ancienne mais toujours d'actualité. Documentation officielle :

Comprendre

Afficher du texte

Tester l'exemple basique ci-dessous :

# Importation de la bibliothèque
from tkinter import *

# Fenêtre principale
fenetre=Tk()

# Ajout d'un texte
message=Label(text='Bonjour...')

# Positionnement du texte dans la fenêtre
message.pack(padx=30, pady=10)

# Affichage de la fenêtre
fenetre.mainloop()

Ajouter une zone de saisie, un bouton

De nombreux objets peuvent être inclus dans la fenêtre. Tester l'exemple ci-dessous :

from tkinter import *

# Fonction appelée en cliquant sur le bouton
def repondre():
  message['text']="Bonjour "+saisie.get()+"!"

# Fenêtre principale
fenetre=Tk()

# Texte
question=Label(text='Quel est ton nom?')
question.pack(padx=30, pady=10)

# Zone de saisie
saisie=Entry()
saisie.pack(padx=30, pady=10)

# Bouton
bouton=Button(text='Valider', command=repondre)
bouton.pack(padx=30, pady=10)

# Autre texte
message=Label(text='Bonjour...')
message.pack(padx=30, pady=10)

fenetre.mainloop()

Effectuer un calcul

L'objectif est de calculer le temps de téléchargement d'un fichier, connaissant :

from tkinter import *

# Fonction appelée en cliquant sur le bouton
def repondre():
  v=saisie1.get()
  v=float(v)
  t=saisie2.get()
  t=float(t)
  d=round(1000*t/v)
  d=str(d)
  message['text']="Durée du transfert : "+d+" s."
  
# Fenêtre principale
fenetre=Tk()

# Texte
question1=Label(text='Débit en ko/s?')
question1.pack(padx=30, pady=10)

# Zone de saisie
saisie1=Entry()
saisie1.pack(padx=30, pady=10)

# Autre texte
question2=Label(text='Taille du fichier en Mo?')
question2.pack(padx=30, pady=10)

# Autre zone de saisie
saisie2=Entry()
saisie2.pack(padx=30, pady=10)

# Bouton
bouton=Button(text='Valider', command=repondre)
bouton.pack(padx=30, pady=10)

# Dernier texte
message=Label(text='Durée du transfert : ...')
message.pack(padx=30, pady=10)

fenetre.mainloop()

Améliorer la présentation

Il s'agit de créer deux cadres dans lesquels seront placées les questions et les zones de saisie, d'ajouter quelques couleurs...

from tkinter import *

# Fonction appelée en cliquant sur le bouton
def repondre():
  v=saisie1.get()
  v=float(v)
  t=saisie2.get()
  t=float(t)
  d=round(1000*t/v)
  d=str(d)
  message['text']="Durée du transfert : "+d+" s."

# Fenêtre principale
fenetre=Tk()
fenetre['bg']='#aabbcc'
fenetre.title(" Calcul de durée ")

# Deux cadres dans la fenêtre principale
cadre1=Frame()
cadre1.pack(padx=30, pady=10, fill=X)
cadre2=Frame()
cadre2.pack(padx=30, pady=10, fill=X)

# Texte et zone de saisie dans le cadre 1
question1=Label(cadre1, text='Débit en ko/s?')
question1.pack(padx=30, pady=10, side=LEFT)
saisie1=Entry(cadre1)
saisie1.pack(padx=30, pady=10, side=RIGHT)

# Texte et zone de saisie dans le cadre 2
question2=Label(cadre2, text='Taille du fichier en Mo?')
question2.pack(padx=30, pady=10, side=LEFT)
saisie2=Entry(cadre2)
saisie2.pack(padx=30, pady=10, side=RIGHT)

# Bouton valider dans la fenêtre principale
bouton=Button(text='Valider', command=repondre)
bouton.pack(padx=30, pady=10)

# Dernier texte dans la fenêtre principale
message=Label(text='Durée du transfert : ...', bg='#aabbcc')
message.pack(padx=30, pady=10)

fenetre.mainloop()

Le résultat :

Dessiner dans une zone graphique

Le code ci-dessous dessine des cercles positionnés au hasard.

from tkinter import *
import random

# Dessine un cercle dans la zone graphique
def Cercle():
  x=random.randint(0,Largeur)
  y=random.randint(0,Hauteur)
  r=20
  Canevas.create_oval(x-r, y-r, x+r, y+r, fill='#9999ff', outline='#0000ff', width='4')

# Efface la zone graphique
def Effacer():
  Canevas.delete(ALL)

# Fenêtre principale
fenetre=Tk()
fenetre.title('Cercles')

# Zone graphique
Largeur=500
Hauteur=300
Canevas=Canvas(fenetre, width=Largeur, height=Hauteur, bg='#ddff88')
Canevas.pack(padx=5, pady=5)

# Boutton dessiner
BoutonDessiner=Button(fenetre, text='Dessiner', command=Cercle)
BoutonDessiner.pack(side=LEFT, padx=5, pady=5)

# Button effacer
BoutonEffacer=Button(fenetre, text='Effacer', command=Effacer)
BoutonEffacer.pack(side=LEFT, padx=5, pady=5)

fenetre.mainloop()

Le résultat :

Pratiquer

Une nuit étoilée

Le but est d'obtenir un logiciel capable de dessiner automatiquement un ciel étoilé. Pour cela, modifier le code dessinant les cercles :

  1. Donner le titre Nuit étoilée à la fenêtre principale.
  2. Mettre du bleu foncé pour la couleur de fond de la zone graphique.
  3. Augmenter les dimensions de la zone graphique avec une largeur de 800 pixels et une hauteur de 500 pixels.
  4. Changer la couleur des cercles pour qu'elle soit jaune pâle.
  5. Dans la fonction Cercle(), modifier le rayon du cercle pour qu'il soit pris au hasard entre 1 et 6.
  6. Ajouter une fonction Cercles(), appelée en cliquant sur le bouton Dessiner, qui dessine trois étoiles à la fois.
  7. Modifier fonction Cercles() pour qu'elle dessine un nombre d'étoiles pris au hasard entre 10 et 20.

Une tempête de neige

Ce travail est libre. A vous de représenter un ciel enneigé!

Approfondir

Modifier le code de calcul du temps de téléchargement pour indiquer sa durée en nombres d'heures, de minutes et de secondes. Une astuce consiste à utiliser les opérateurs :

Début de solution :

def repondre():
  v=float(saisie1.get())
  t=float(saisie2.get())
  d=round(1000*t/v)
  nb_min=str(d//60)
  nb_sec=str(d%60)
  if nb_min=="0":
    message['text']="Durée du transfert : "+nb_sec+" s."
  else:
    message['text']="Durée du transfert : "+nb_min+" min "+nb_sec+" s."