Retour aux projets // TP Python — Bibliothèque & GUI
📊

TP Python — Bibliothèque & Interface Graphique

Application de gestion de bibliothèque avec interface CLI et GUI CustomTkinter. Gestion des emprunts/retours, utilisateurs et ressources avec persistance JSON.

PythonCustomTkinter JSONPOOGUI

Interface graphique interactive (simulation)

Simulation fidèle de l'interface CustomTkinter — données réelles du db.json
Gestion de Bibliothèque
Gestion de Bibliothèque
// db.json (live)

Code source

bibliotheque.py
graph.py (GUI)
main.py (CLI)
bibliotheque.py
import json, os
from ressource import Ressource

class Bibliotheque:
    def __init__(self, fichier="db.json"):
        self.fichier = fichier
        self.ressources = {}
        self.utilisateurs = set()
        self.charger()

    def sauvegarder(self):
        data = {
            "utilisateurs": list(self.utilisateurs),
            "ressources": [r.to_dict() for r in self.ressources.values()]
        }
        with open(self.fichier, "w", encoding="utf-8") as f:
            json.dump(data, f, indent=2, ensure_ascii=False)

    def charger(self):
        if not os.path.exists(self.fichier):
            self.sauvegarder(); return
        try:
            with open(self.fichier, "r", encoding="utf-8") as f:
                data = json.load(f)
        except (json.JSONDecodeError, ValueError):
            data = {"utilisateurs": [], "ressources": []}
            self.sauvegarder()
        self.utilisateurs = set(data.get("utilisateurs", []))
        self.ressources = {r["id"]: Ressource.from_dict(r) for r in data.get("ressources", [])}

    def ajouter_ressource(self, identifiant, nom):
        if identifiant in self.ressources:
            raise Exception("Une ressource avec cet ID existe déjà.")
        self.ressources[identifiant] = Ressource(identifiant, nom)
        self.sauvegarder()

    def ajouter_utilisateur(self, nom):
        self.utilisateurs.add(nom)
        self.sauvegarder()

    def emprunter(self, nom, id_ressource):
        if nom not in self.utilisateurs:
            raise Exception("Utilisateur inconnu.")
        if id_ressource not in self.ressources:
            raise Exception("Ressource introuvable.")
        self.ressources[id_ressource].emprunter(nom)
        self.sauvegarder()

    def rendre(self, id_ressource):
        if id_ressource not in self.ressources:
            raise Exception("Ressource introuvable.")
        self.ressources[id_ressource].rendre()
        self.sauvegarder()

    def afficher(self):
        for r in self.ressources.values():
            statut = "Disponible" if r.est_disponible() else f"Empruntée par {r.emprunte_par}"
            print(f"[{r.id}] {r.nom} — {statut}")
graph.py — Interface CustomTkinter
import customtkinter as ctk
from tkinter import messagebox
from bibliotheque import Bibliotheque

ctk.set_appearance_mode("dark")
ctk.set_default_color_theme("blue")

b = Bibliotheque()
ADMIN_PASSWORD = "password"

app = ctk.CTk()
app.title("Gestion de Bibliothèque")
app.geometry("500x450")

def fenetre_emprunter():
    win = ctk.CTkToplevel(app)
    win.title("Emprunter une ressource")
    win.geometry("400x400")
    biblio = Bibliotheque()

    ctk.CTkLabel(win, text="Ressources disponibles :").pack(pady=5)
    box = ctk.CTkTextbox(win, width=350, height=150)
    box.pack()
    for r in biblio.ressources.values():
        statut = "Disponible" if r.est_disponible() else f"Empruntée par {r.emprunte_par}"
        box.insert("end", f"[{r.id}] {r.nom} - {statut}\n")
    box.configure(state="disabled")

    ctk.CTkLabel(win, text="Nom utilisateur :").pack(pady=5)
    entry_user = ctk.CTkEntry(win); entry_user.pack()
    ctk.CTkLabel(win, text="ID ressource :").pack(pady=5)
    entry_id = ctk.CTkEntry(win); entry_id.pack()

    def valider():
        try:
            biblio.emprunter(entry_user.get().strip(), entry_id.get().strip())
            messagebox.showinfo("Succès", "Ressource empruntée avec succès.")
            win.destroy()
        except Exception as e:
            messagebox.showerror("Erreur", str(e))

    ctk.CTkButton(win, text="Valider", command=valider).pack(pady=15)

def fenetre_rendre():
    win = ctk.CTkToplevel(app)
    win.title("Rendre une ressource")
    win.geometry("350x200")
    ctk.CTkLabel(win, text="ID ressource :").pack(pady=5)
    entry_id = ctk.CTkEntry(win); entry_id.pack()

    def valider():
        try:
            b.rendre(entry_id.get())
            ctk.CTkLabel(win, text="Ressource rendue !", text_color="green").pack(pady=10)
        except Exception as e:
            ctk.CTkLabel(win, text=f"Erreur : {e}", text_color="red").pack(pady=10)

    ctk.CTkButton(win, text="Valider", command=valider).pack(pady=15)

def fenetre_admin():
    win = ctk.CTkToplevel(app)
    win.title("Mode Administrateur")
    win.geometry("400x500")

    def check_password():
        if entry_mdp.get() != ADMIN_PASSWORD:
            lbl_result.configure(text="Mot de passe incorrect", text_color="red")
        else:
            lbl_result.configure(text="Accès autorisé", text_color="green")
            frame = ctk.CTkFrame(win); frame.pack(pady=20)
            ctk.CTkButton(frame, text="Ajouter utilisateur", width=250).pack(pady=5)
            ctk.CTkButton(frame, text="Ajouter ressource",   width=250).pack(pady=5)
            ctk.CTkButton(frame, text="Supprimer utilisateur", width=250).pack(pady=5)
            ctk.CTkButton(frame, text="Supprimer ressource",   width=250).pack(pady=5)
            ctk.CTkButton(frame, text="Voir utilisateurs",     width=250).pack(pady=5)
            ctk.CTkButton(frame, text="Voir ressources",       width=250).pack(pady=5)

    ctk.CTkLabel(win, text="Mot de passe admin :").pack(pady=5)
    entry_mdp = ctk.CTkEntry(win, show="*"); entry_mdp.pack()
    ctk.CTkButton(win, text="Valider", command=check_password).pack(pady=10)
    lbl_result = ctk.CTkLabel(win, text=""); lbl_result.pack()

def fenetre_utilisateur():
    win = ctk.CTkToplevel(app)
    win.title("Mode Utilisateur")
    win.geometry("400x350")
    ctk.CTkButton(win, text="Emprunter une ressource", width=250, command=fenetre_emprunter).pack(pady=10)
    ctk.CTkButton(win, text="Rendre une ressource",    width=250, command=fenetre_rendre).pack(pady=10)

ctk.CTkLabel(app, text="Gestion de Bibliothèque", font=("Arial", 22)).pack(pady=20)
ctk.CTkButton(app, text="Mode utilisateur",    width=250, command=fenetre_utilisateur).pack(pady=10)
ctk.CTkButton(app, text="Mode administrateur", width=250, command=fenetre_admin).pack(pady=10)
ctk.CTkButton(app, text="Quitter",             width=250, command=app.destroy).pack(pady=20)

app.mainloop()
main.py — Interface CLI
from bibliotheque import Bibliotheque

b = Bibliotheque()
ADMIN_PASSWORD = "password"

while True:
    print("\n=== MENU PRINCIPAL ===")
    print("1. Mode utilisateur\n2. Mode administrateur\n0. Quitter")
    choix = input("Choisissez : ")

    if choix == "1":
        while True:
            print("\n1. Emprunter\n2. Rendre\n3. Afficher\n0. Retour")
            c = input("Choix : ")
            if c == "1":
                u = input("Utilisateur : ")
                i = input("ID ressource : ")
                try: b.emprunter(u, i); print("Emprunt réussi.")
                except Exception as e: print("Erreur :", e)
            elif c == "2":
                i = input("ID ressource : ")
                try: b.rendre(i); print("Ressource rendue.")
                except Exception as e: print("Erreur :", e)
            elif c == "3": b.afficher()
            elif c == "0": break

    elif choix == "2":
        if input("Mot de passe : ") != ADMIN_PASSWORD:
            print("Incorrect."); continue
        while True:
            print("\n1. Ajouter user\n2. Ajouter ressource\n3. Suppr user\n4. Suppr ressource\n0. Retour")
            c = input("Choix : ")
            if c == "1":
                b.ajouter_utilisateur(input("Nom : "))
            elif c == "2":
                b.ajouter_ressource(input("ID : "), input("Nom : "))
            elif c == "0": break

    elif choix == "0":
        print("Au revoir."); break