Projet "calculatrice graphique programmeur"

Ce projet a pour but de découvrir la programmation en Python utilisant une interface graphique.
Il existe plusieurs modules Python permettant d’exploiter les interfaces graphiques.
Le plus simple est le module tkinter présent lors de l’installation du langage Python.
Voici quelques autres modules pour programmer avec une interface graphique :

Ces 3 autres modules pour les interfaces graphiques ont un meilleur rendu visuel que tkinter mais sont plus délicates à prendre en main.
Dans ce projet nous utiliserons le module tkinter

Une première fenêtre graphique

Voici un code minimal pour afficher une fenêtre graphique de dimension 600x600 (en pixels) avec un titre ("Calculatrice programmeur").

À faire vous-même 1

Testez ce programme à l'aide de Spyder :


from tkinter import Tk

fenetre=Tk()
fenetre.geometry("600x600")
fenetre.title("Calculatrice programmeur")
fenetre.mainloop()
			

Vous devriez obtenir l'affichage de la fenêtre suivante :

Insérer des éléments graphiques dans notre fenêtre tkinter

Il est possible d'insérer des éléments graphiques ( nommés "widgets" en anglais) tels que :

Il existe un grand nombre de widgets dans tkinter : case à cocher, boutons radio, liste déroulante, zone graphique pour dessiner (canvas), fenêtres d'alerte, etc ....

À faire vous-même 2

Testez ce programme à l'aide de Spyder :


from tkinter import Tk,Label,Button,messagebox

def cliqueBouton():
    messagebox.showinfo("Bravo", "Super cliqueur !")

fenetre=Tk()
fenetre.geometry("600x200")
fenetre.title("Calculatrice programmeur")
mon_label = Label(fenetre, text="Hello World",font=("Courier", 20))
mon_label.pack()
mon_bouton = Button(fenetre, text="OK",command=cliqueBouton,font=("Courier", 20))
mon_bouton.pack()
fenetre.mainloop()
			

Vous devriez obtenir l'affichage de la fenêtre suivante :

Et si on clique sur le bouton "OK", on obtient l'affichage d'une fenêtre d'information :

Quelques explications sur ces lignes de code :

La ligne mon_label = Label(fenetre, text="Hello World",font=("Courier", 20)) crée un widget de type Label.
Il est rattaché à la fenêtre fenetre, le texte associé à ce Label est "Hello World" (text="Hello World").
Enfin le texte est affiché dans une police de caractère "Font" et de taille 20. (font=("Courier", 20)).

La ligne mon_label.pack() permet de disposer le label dans la fenêtre graphique.
Nous verrons plus loin un autre gestionnaire de positionnement basé sur un placement des composants graphiques dans une grille.
Cet autre gestionnaire de positionnement est géré à l'aide de la méthode .grid().

La ligne mon_bouton = Button(fenetre, text="OK",command=cliqueBouton,font=("Courier", 20)) crée un widget de type Button.
Il est rattaché à la fenêtre fenetre, le texte associé à ce Button est "OK" (text="OK").
Lorsque l'on clique sur ce bouton, un appel à la méthode cliqueBouton() est effectué. (command=cliqueBouton
Enfin le texte est affiché dans une police de caractère "Font" et de taille 20. (font=("Courier", 20))

Enfin, dans le corps de la méthode cliqueBouton(), la ligne de code messagebox.showinfo("Bravo", "Super cliqueur !") permet d'afficher une fenêtre d'information.

Il est possible de réaliser de nombreuses actions avec un module de gestion des interfaces graphiques comme tkinter.
Vous pouvez suivre un tutoriel en ligne plus complet sur l'utilisation de tkinter comme celui-ci ou celui-là par exemple.
Vous pouvez aussi vous référer à la document officielle de tkinter : ici.

Le projet "calculatrice graphique programmeur"

Vous devez écrire un programme Python utilisant la bibliothèque tkinter qui permet d'implémenter les fonctionnalités de base d'une calculatrice programmeur.

On peut pour cela s'inspirer de la calculatrice programmeur fournie par windows :

Voici la liste des fonctionnalités à développer qui vous sont demandées dans ce projet :

Conseils pour le projet

Voici un squelette de code Python, qui définit les widgets graphiques avec les méthodes callback (c'est à dire les fonctions appelées lorsque l'on clique sur un bouton) définies mais avec leur corps vide.
Ce squelette peut vous servir de base pour votre projet.


from tkinter import *
from tkinter import messagebox


def choix_base_hex():
    return
    
def choix_base_dec():
   return

def choix_base_oct():
    return

def choix_base_bin():
    return

def reset_background_color_buttons():
    return
    
def bouton_saisi(bouton):
   return
      
def choix_lg_codage_oct():
   return
    
           
BG_BASE_CHOISIE = "#6699ff"

ENTIERS_SIGNES = True
if ENTIERS_SIGNES:
    PAVE_SAISI = [["A","B","7","8","9"],["C","D","4","5","6"],["E","F","1","2","3"],[" ","±","0"," ","EFF"]]
else:
    PAVE_SAISI = [["A","B","7","8","9"],["C","D","4","5","6"],["E","F","1","2","3"],[" "," ","0"," ","EFF"]]

base_courante = "DEC"
fenetre=Tk()
fenetre.geometry("600x600")
fenetre.withdraw()
fenetre.title("Calculatrice programmeur")
frame_resultat = Frame(fenetre)
frame_resultat.grid(column = 0,row = 0,sticky=E)
resultat = StringVar()
lbl_resultat = Label(frame_resultat, textvariable=resultat,font=("Courier", 20))
resultat.set("0")
nombre_courant_base_10 = 0
lbl_resultat.grid(column = 0,row = 0,sticky=E) 
frame_bases = Frame(fenetre,width=500)
frame_bases.grid(column = 0,row = 1,sticky=W)

btn_base_hex = Button(frame_bases, text="HEX",command=choix_base_hex,font=("Courier", 15))
orig_color = btn_base_hex.cget("background")
btn_base_hex.grid(column = 0,row = 0,sticky=W) 

resultat_hex = StringVar()
lbl_resultat_hex = Label(frame_bases, textvariable=resultat_hex,font=("Courier", 15))
resultat_hex.set("0")
lbl_resultat_hex.grid(column = 1,row = 0,sticky=W) 

btn_base_dec = Button(frame_bases, text="DEC",bg = BG_BASE_CHOISIE,command=choix_base_dec,font=("Courier", 15))
btn_base_dec.grid(column = 0,row = 1) 
resultat_dec = StringVar()
lbl_resultat_dec = Label(frame_bases, textvariable=resultat_dec,font=("Courier", 15))
resultat_dec.set("0")
lbl_resultat_dec.grid(column = 1,row = 1,sticky=W) 

btn_base_oct = Button(frame_bases, text="OCT",command=choix_base_oct,font=("Courier", 15))
btn_base_oct.grid(column = 0,row = 2) 
resultat_oct = StringVar()
lbl_resultat_oct = Label(frame_bases, textvariable=resultat_oct,font=("Courier", 15))
resultat_oct.set("0")
lbl_resultat_oct.grid(column = 1,row = 2,sticky=W) 

btn_base_bin = Button(frame_bases, text="BIN",command=choix_base_bin,font=("Courier", 15))
btn_base_bin.grid(column = 0,row = 3) 
resultat_bin = StringVar()
lbl_resultat_bin = Label(frame_bases, textvariable=resultat_bin,font=("Courier", 15))
resultat_bin.set("0")
lbl_resultat_bin.grid(column = 1,row = 3,sticky=W) 

frame_padding_1 = Frame(fenetre,height=30)
frame_padding_1.grid(column = 0,row = 2)

frame_lg_codage = Frame(fenetre,height=30)
frame_lg_codage.grid(column = 0,row = 3)
nb_octets = 2
lg_codage = StringVar()
btn_lg_codage = Button(frame_lg_codage,textvariable=lg_codage,command=choix_lg_codage_oct,font=("Courier", 15))
lg_codage.set("2 octets")
btn_lg_codage.grid(column = 0,row = 0) 

frame_padding_1 = Frame(fenetre,height=30)
frame_padding_1.grid(column = 0,row = 4)

frame_chiffres = Frame(fenetre)
frame_chiffres.grid(column = 0,row = 5,sticky=W)
lst_btn_pave_saisi = []
lig = 0
for l in PAVE_SAISI:
    lig_btn_chiffres = []
    col = 0
    for c in l:
        b = Button(frame_chiffres, width=3,text=c,font=("Courier", 20),command=lambda bouton = c: bouton_saisi(bouton))
        lig_btn_chiffres.append(b)
        if c != " ":
            b.grid(column = col,row = lig) 
        col += 1
    lst_btn_pave_saisi.append(lig_btn_chiffres)
    lig += 1

fenetre.update()
fenetre.deiconify()
fenetre.mainloop()
			

Explications sur ce code :

Les éléments graphiques sont placés dans une grille avec la méthode .grid(ligne,colonne).

Les boutons du pavé de saisie contenant les chiffres possibles, le bouton ± et le bouton "EFF" sont regroupés dans une matrice (une liste de listes) nommée lst_btn_pave_saisi.

Vous aurez besoin de fonctions qui font des conversions d'une base vers une autre.
Vous pouvez par exemple, vous limitez à passer toujours par la base 10, et n'utiliser que deux fonctions de conversion : une de la base 10 vers la base b et une autre de la base b vers la base 10 (avec b = 2,8 ou 16).

Vous aurez également besoin d'une fonction qui contrôle que le nombre courant est toujours compris dans la plage autorisée selon la longueur de codage (sur 1, 2 ou 4 octets.)

Voici une petite vidéo présentant cette calculatrice programmeur codée en Python avec tkinter et avec les fonctionnalités demandées :

Prolongements possibles

Si vous avez le temps vous pouvez ajouter d'autres fonctionnalités à votre calculatrice programmeur.
Par exemple, les 4 opérations, les opérateurs logiques "Ou" "Et", "Non", "Ou Exclusif" (qui opérent bit à bit sur les entiers codés en binaire).