Les interfaces graphiques en Python permettent de créer des applications avec une interface utilisateur graphique, offrant ainsi une expérience plus visuelle et interactive. Avec des bibliothèques tel que par exemple Tkinter, Python simplifie le développement d’interfaces utilisateur, que ce soit pour des applications de bureau, des outils de visualisation ou des applications mobiles.
Sommaire
Introduction :
Les interfaces graphiques en Python représentent un moyen puissant de créer des applications interactives, offrant une expérience utilisateur intuitive et visuellement attrayante. Ce projet a pour objectif principal de concevoir une interface graphique permettant l’affichage, la modification et la suppression d’éléments au sein d’une base de données à l’aide de la programmation en Python. Les outils clés employés dans ce projet incluent Tkinter pour la conception de l’interface utilisateur et pandas pour la manipulation des données de la base.
Le compte rendu suivra une structure organisée, mettant en valeur les aspects cruciaux du projet, de la conception de l’interface graphique à l’intégration de la base de données. Les grandes sections de ce compte rendu incluront la conception de l’interface graphique, l’intégration de la base de données, les fonctionnalités principales, la gestion des erreurs et les opportunités d’amélioration, concluant avec un récapitulatif des points saillants du projet. Ces sections aideront à fournir une vision globale et détaillée du processus de développement de l’interface graphique Python dédiée à la gestion de bases de données.
Fonctionnalités Principales :
L’utilisation de la bibliothèque pandas s’avère essentielle pour la manipulation agile des données au sein de notre interface. Cette section explore les techniques employées pour extraire, modifier et supprimer des données, assurant ainsi une cohérence entre les informations présentées à l’utilisateur et celles stockées dans la base de données. Tout comme Tkinter, qui est une bibliothèque d’interface graphique en Python qui permet de créer des applications avec une interface utilisateur visuelle, facilitant ainsi le développement d’applications interactives.
Affichage :
Le processus d’affichage se déroule en plusieurs parties. Pour débuter, nous avons opté pour la création d’une nouvelle fenêtre à laquelle nous avons attribué des dimensions de 800×1000 (une décision basée sur nos préférences personnelles).
def affichage(): # Créer une nouvelle fenêtre pour afficher le Pokédex fenetreupdate = Toplevel() fenetreupdate.title("Pokédex") fenetreupdate.geometry("800x1000")
Ensuite, pour connecter le script à la base de données (sous format Excel), en considérant que « bdd » représente notre base de données et que l’argument engine='openpyxl'
est utilisé pour orienter pandas vers le module openpyxl
. Cela permet à pandas de lire et d’écrire des fichiers Excel dans le format spécifique .xlsx
.
excel_data = pd.read_excel("bdd.xlsx", engine='openpyxl')
Enfin, pour exploiter chaque ligne et chaque colonne, l’utilisation d’une double boucle for s’est avérée la plus pertinente pour nous. Nous avons également souhaité personnaliser la première colonne (le nom des Pokémon) en appliquant une police en gras pour les mettre en valeur. De plus, nous avons ajouté un espacement entre les données du tableur afin d’améliorer la présentation générale.
for index, row in excel_data.iterrows(): for col_index, value in enumerate(row): label = Label(fenetreupdate, text=str(value)) if col_index == 0: label.config(font=("Arial", 14, "bold")) label.grid(row=index+1, column=col_index, padx=50, pady=10, columnspan=2)
Nous avons ensuite fait face a un problème de place car notre base de donnée était trop longue. Nous avons rajouté une scrollbar . Pour cela, on a du d’abord définir un canva qui entoure toute la fenêtre. Puis, configurer ou se trouve la barre par rapport a la fenêtre.
canvas = Canvas(fread) canvas.pack(side=LEFT, fill=BOTH, expand=True) scrollbar = Scrollbar(fread, orient=VERTICAL, command=canvas.yview) scrollbar.pack(side=RIGHT, fill=Y) canvas.configure(yscrollcommand=scrollbar.set)
Puis, on a du créer une fonction qui lierai l’évènement du mouvement de la souris avec la scrollbar:
def bardef(event): canvas.configure(scrollregion=canvas.bbox('all')) frame.bind('<Configure>', bardef) canvas.bind_all("<MouseWheel>", lambda event: canvas.yview_scroll(int(-1 * (event.delta / 120)), "units"))
L’arborescence des fenêtres
Pour avoir un rendu de pokedex crédible, nous avons du trouver une bonne mise en forme des différentes fonctions. On est donc parti d’une première fenêtre qui afficherait deux boutons: Un pour afficher la base de donnée et un pour modifier le pokédex. La fenêtre « Modifier le pokédex » n’utilise pas de sql car elle ne modifie pas de base de donnée, elle répertorie les actions qu’on peut exécuter sur le pokedex ( ajouter, modifier et supprimer) sous forme de trois autres boutons.
bouton3 = Button(fmodif, text="Ajouter un Pokemon", font=("Consolas", 15), bg="white", fg="black", command=create, width=50, height=3) bouton4 = Button(fmodif, text="Modifier un Pokemon", font=("Consolas", 15), bg="white", fg="black", command=update, width=50, height=3) bouton5 = Button(fmodif, text="Supprimer un Pokemon", font=("Consolas", 15), bg="white", fg="black", command=delete, width=50, height=3)
Voici les boutons que nous avons utilisé tout le long du code. Il fallait a chaque fois les appeler avec avec la fonction pack(). Un des erreurs que nous avons rencontré est de mettre tout les boutons a la fin du code alors qu’il fallait les placer dans leurs fonctions respectives.
La fonction create
Pour la fonction create, nous avons pensé à faire plusieurs champ de saisie a la suite afin que l’utilisateur puisse rentrer toutes les données du nouveau Pokémon. Voici a quoi ressemble un des champs de saisie:
#champ de saisie nom fr nom_pokemon_label = Label(fcreate, text="Entrez le nom du nouveau Pokémon", font=("Arial", 10), bg="red") nom_pokemon_label.pack(pady=10) nom_pokemon_entry = Entry(fcreate, bg="white") nom_pokemon_entry.pack(pady=10)
La variable ‘nom_pokemon_label’ sert a configurer la zone de texte qui permet de savoir a quoi sert le champ de saisie. La fonction Label sert a créer et modifier le style d’une zone de texte et ici, le texte au dessus du champ de saisie. La variable ‘nom_pokemon_entry’ sert a créer le champ de saisie et modifier son apparence. Les deux variables sont appelées avec la fonction pack() qui fait apparaitre les éléments graphiques.
Après avoir fait tout les champs de saisie de chacune des données, on a créé un bouton sauvegarde afin d’enregistrer les nouvelles données dans le fichier.
Dans la partie sql, on a donc d’abord créé une fonction enregistrer() qui prend en paramètre tout les noms de données afin d’enregistrer chaque valeur. Ensuite, nous avons créé la variable ‘nv_ligne’. Avec la commande DataFrame de panda, elle crée une nouvelle ligne en prenant en compte les colonnes du fichier excel. Avec a commande concat, elle enregistre les données en fonction du type de donnée dans chacune des colonnes de la nouvelle ligne. Le ignore_index sert a ne pas prendre en compte les id d’origines.
#création de la ligne du nv pokemon nv_ligne = pd.DataFrame([[idtf, nom_pokemon, nom_anglais, type_pokemon, type_secondaire, pv, attaque, defense]], columns=excel_data.columns) #enregistrer les données dans la nouvelle ligne excel_data = pd.concat([excel_data, nv_ligne], ignore_index=True)
Comme a la fin de chaque fenêtre, nous utilisons destroy() pour ne pas accumuler les fenêtres. Donc, après avoir appuyé sur le bouton sauvegarde, la fenêtre se ferme mais un print sur la console d’exécution nous montre que le pokemon a été enregistré.
La fonction update
Nous avons utilisé a peu près le même fonctionnement pour les autres fonctions: une fonction qui crée la fenêtre avec la bibliothèque de tkinter et une autre qui modifie et enregistre les données de la base de données avec les bibliothèques de panda et sqlite3.
Donc, nous avons commencé par une fonction update qui génère la fenètre et son apparence. Nous avons choisis, pour modifier les données de créer d’abord un champ de saisie pour rentrer le nom Français du pokemon a modifier, puis une Combobox ( comme un champ de saisie mais ou on sélectionne la donnée dans une liste) afin de sélectionner la donnée a modifier, puis, un autre champ de saisie pour donc modifier le contenu de la donnée. Nous avons aussi ajouté un bouton sauvegarder qui utilise la fonction update_data qui prend en paramètre chaque variable utilisée par les champ de saisie et la combobox.
#champ de saisie pokemon a modifier userlbl = Label(fupdate, text="Entrez le nom du pokémon que vous voulez modifier", font=("Arial", 12), bg="red") userlbl.pack(pady=10) nom_pokemon = Entry(fupdate, bg="white") nom_pokemon.pack(pady=10) #combobox type de donnée a modif liste_donnees = ["Indice", "Nom français", "Nom anglais", "Type", "Type secondaire", "PV", "Attaque", "Défense"] comboboxlbl = Label(fupdate, text="Choisissez le type de donnée à modifier", font=("Arial", 12), bg="red") comboboxlbl.pack(pady=10) listeCombo = ttk.Combobox(fupdate, values=liste_donnees) listeCombo.pack(pady=10) #cds nv donnée userlbl = Label(fupdate, text="Entrez la nouvelle donnée", font=("Arial", 12), bg="red") userlbl.pack(pady=10) nv_donnée_entry = Entry(fupdate, bg="white") nv_donnée_entry.pack(pady=10)
Les champs de saisies sont les même que ceux de la fonction ajouter. Pour la Combobox, c’est le meme principe sauf qu’il faut ajouter une liste avant ou on a rentré les différents types de données et qu’on appelle dans la variable listeCombo avec ‘values’.
Pour la sauvegarde, on a utilisé une fonction update_data() qui prend en paramètre le nom du pokémon a modifier, le type de donnée a modifier et la nouvelle valeur. Pour mettre a jour les données, on a du écrire un enchainement de elif car il faut que l’utilisateur puisse modifier chaque donnée et que donc le code est différent pour chaque donnée.
#maj des données if type_donnee == "Indice": excel_data.loc[excel_data['Nom français'] == nom_pokemon, 'Indice'] = nv_val elif type_donnee == "Nom français": excel_data.loc[excel_data['Nom français'] == nom_pokemon, 'Nom français'] = nv_val elif type_donnee == "Nom anglais": excel_data.loc[excel_data['Nom français'] == nom_pokemon, 'Nom anglais'] = nv_val elif type_donnee == "Type": excel_data.loc[excel_data['Nom français'] == nom_pokemon, 'Type'] = nv_val elif type_donnee == "Type secondaire": excel_data.loc[excel_data['Nom français'] == nom_pokemon, 'Type secondaire'] = nv_val elif type_donnee == "PV": excel_data.loc[excel_data['Nom français'] == nom_pokemon, 'PV'] = nv_val elif type_donnee == "Attaque": excel_data.loc[excel_data['Nom français'] == nom_pokemon, 'Attaque'] = nv_val elif type_donnee == "Défense": excel_data.loc[excel_data['Nom français'] == nom_pokemon, 'Défense'] = nv_val
A chaque fois on commence avec une vérification pour savoir quel est le type de donnée, puis, avec la fonction loc(), on cherche dans le fichier d’abord le pokémon avec son nom Français, puis on trouve le type de donnée a modifier et on le remplace par la nouvelle valeur. Les données sont ensuite enregistrées dans la base de donnée avec ‘excel_data.to_excel’ comme dans les autres fonctions, la fenêtre et détruite un print affiche que les données ont bien été modifiées.
La fonction delete
Pour la suppression d’un pokemon nous avons utilisé trois fonctions. Dans la première, ont créé la fenêtre et on y ajoute un champ de saisi. En effet, on a seulement besoin du nom du Pokemon puisqu’il s’agit de supprimer toutes les données de ce Pokémon a partir de son nom. Les deux autres fonctions sont liées puisque la première, pokemon_supp() sert a trouver le nom du pokemon qui correspond et utiliser la deuxième fonction suppression() qui met a jour la base de donnée avec ‘to_excel’.
def pokemon_supp(supp_entry): #enregistre le nom rentré nom_pokemon = supp_entry.get() #supprime de la base suppression(nom_pokemon) def suppression(nom_pokemon): #connecte le xlsx excel_data = pd.read_excel("base de donnée.xlsx") # remplace par le nom de la collone du nom excel_data = excel_data[excel_data['Nom français'] != nom_pokemon] # recrée le exel sans le pokemon excel_data.to_excel("base de donnée.xlsx", index=False)
La méthode .get() sert a utiliser une variable avec entry, donc ici la variable du champ de saisie. Dans la fonction suppression(), on connecte d’abord les données du fichier grâce au ‘read_excel’ de panda, puis on sélectionne toutes les lignes du fichier sauf celle du pokémon sélectionné et on recrée la base de donnée avec.
Conclusion
En résumé, ce projet d’interface graphique en Python pour la gestion d’une base de données a été une expérience enrichissante. Nous avons exploré la création d’une fenêtre comportant des boutons, chacun dédié à une fonctionnalité spécifique. Nous avons également mis en place une zone de champs de texte pour manipuler les données à l’intérieur. Bien que cela ait été complexe, cette expérience nous a permis d’approfondir nos connaissances en programmation Python.
Merci d’avoir lu notre article, voici la base de donnée et le script a télécharger.
Étudiant en spécialité NSI en classe de Terminale en 2024.