IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

input.get() ne fonctionne pas


Sujet :

Python

  1. #1
    Invité de passage
    Homme Profil pro
    Retraité
    Inscrit en
    Octobre 2025
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2025
    Messages : 26
    Par défaut input.get() ne fonctionne pas
    Bonjour,
    je suis nouveau sur ce forum donc je peux me tromper. Merci de m'aider à corriger.
    Retraité je suis engagé dans une association humanitaire et j'ai développé un petit programme pour cette association en VBA.
    Pour l'heure je voudrais essayer de comprendre la programmation en Python.
    J'ai tester un petit programme de saisie de données et récupération de celles-ci pour affichage mais cela ne fonctionne pas.
    J'uilise input.get() pour remplir une variable avec le conenu de la saisie mais seul le texte par défaut apparait.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    import tkinter as tk
    from tkinter import font
    from tkinter import *
     
    app = tk.Tk()
    app.title('Assistance Humanitaire Internationale')
    app.geometry("1000x500")
     
    custom_font = font.Font(family="Helvetica", size=14, weight="bold")
     
    labelTitre1 = tk.Label(app, text="SAISIE ADHERENTS", fg="blue", bg="#FF0", font=custom_font)
    labelTitre1.place(x=500, y=0) #              x = du bord gauche - y= du haut
    labelTitre2 = tk.Label(app, text="--------------------------------------")
    labelTitre2.place(x=500, y=25)
    #-----
    labelNom = tk.Label(app, text="NOM", fg="blue", bg="#FF0")
    labelNom.place(x=0, y=50)
    custom_font = font.Font(family="Helvetica", size=8, weight="bold")
    labelNom2 = tk.Label(app, text="ATTENTION: utiliser le - pour les noms composés", fg="Red", bg="#0ff", font=custom_font)
    labelNom2.place(x=300, y=50)
    labelPrenom = tk.Label(app, text="PRENOM", fg="blue", bg="#FF0")
    labelPrenom.place(x=0, y=75)
    labelPrenom2 = tk.Label(app, text="ATTENTION: utiliser le - pour les prénoms composés", fg="Red", bg="#0ff", font=custom_font)
    labelPrenom2.place(x=300, y=75)
    labelAdresse1 = tk.Label(app, text="Adresse1")
    labelAdresse1.place(x=0, y=100)
    labelAdresse2 = tk.Label(app, text="Adresse2")
    labelAdresse2.place(x=0, y=125)
    labelCpostal = tk.Label(app, text="Code Postal")
    labelCpostal.place(x=0, y=150)
    labelVille = tk.Label(app, text="Ville")
    labelVille.place(x=325, y=150)
    labelTphfixe = tk.Label(app, text="Tph fixe")
    labelTphfixe.place(x=0, y=175)
    labelTphport = tk.Label(app, text="Tph portable")
    labelTphport.place(x=325, y=175)
    labelMail = tk.Label(app, text="Mail")
    labelMail.place(x=0, y=200)
     
    labelAdhesion = tk.Label(app, text="Année Adhésion")
    labelAdhesion.place(x=700, y=50)
    labelNaissance = tk.Label(app, text="Dete de naissance")
    labelNaissance.place(x=700, y=75)
    labelProfession = tk.Label(app, text="Profession")
    labelProfession.place(x=700, y=100)
    labelLettre = tk.Label(app, text="Lettre info")
    labelLettre.place(x=700, y=125)
    labelLettre1 = tk.Label(app, text="Tapez O ou N", fg="Red", bg="#0ff")
    labelLettre1.place(x=850, y=125)
    labelCotisation = tk.Label(app, text="Année Cotisation", fg="Red", bg="Yellow")
    labelCotisation.place(x=700, y=150)
     
    entryNom = tk.Entry(app, width=30)
    entryNom.insert(0, "Entrez votre nom ici")
    Lenom = entryNom.get()
     
    entryPrenom = tk.Entry(app, width=30) #width = longeur zone de saisie = largeur de la colonne
    entryPrenom.insert(0, "Entrez votre prénom ici")
    Leprenom = entryPrenom.get()
     
    entryAdresse1 = tk.Entry(app, width=40)
    entryAdresse2 = tk.Entry(app, width=40)
    entryCpostal= tk.Entry(app, width=5)
    entryVille = tk.Entry(app, width=40)
    entryTphfixe = tk.Entry(app, width=12)
    entryTphport = tk.Entry(app, width=12)
    entryMail = tk.Entry(app, width=40)
    entryAdhesion = tk.Entry(app, width=4)
    entryNaissance = tk.Entry(app, width=10)
    entryProfession = tk.Entry(app, width=25)
    entryLettre = tk.Entry(app, width=1)
    entryCotisation = tk.Entry(app, width=4)
     
    # x = du bord gauche - y= du haut
    entryNom.place(x=85, y=50)
    entryPrenom.place(x=85, y=75)
    entryAdresse1.place(x=85, y=100)
    entryAdresse2.place(x=85, y=125)
    entryCpostal.place(x=85, y=150)
    entryVille.place(x=410, y=150)
    entryTphfixe.place(x=85, y=175)
    entryTphport.place(x=410, y=175)
    entryMail.place(x=85, y=200)
    entryAdhesion.place(x=825, y=50)
    entryNaissance.place(x=825, y=75)
    entryProfession.place(x=825, y=100)
    entryLettre.place(x=825, y=125)
    entryCotisation.place(x=825, y=150)
    #----------------------
     
    Button0 = tk.Button(app, text="VALIDER")
    Button0.place(x=0, y=450)
     
    Button1 = tk.Button(app, text="MODIFIER")
    Button1.place(x=100, y=450)
    Button2 = tk.Button(app, text="SUPPRIMER")
    Button2.place(x=200, y=450)
    Button3 = tk.Button(app, text="QUITTER",command = quit)
    Button3.place(x=300, y=450)
     
    print("Bonjour " + Lenom +" " + Leprenom)
     
    app.mainloop()

    Pouvez-vous m'aider pourquoi "Lenom = entryNom.get()" ne fonctionne pas
    erci de votre aide et de vos explications.
    A vous lire

  2. #2
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 779
    Par défaut
    Hello,

    Le problème principal :

    Vous appelez entryNom.get() immédiatement après avoir créé le widget Entry, AVANT que l'utilisateur n'ait eu le temps de saisir quoi que ce soit. Le code s'exécute de manière séquentielle, donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    entryNom = tk.Entry(app, width=30)  # Création du champ
    entryNom.insert(0, "Entrez votre nom ici")  # Texte par défaut
    Lenom = entryNom.get()  # Récupération IMMEDIATE = "Entrez votre nom ici"
    À ce moment, l'utilisateur n'a pas encore vu la fenêtre ! La variable Lenom contient donc le texte par défaut.

    Solutions possibles :

    Solution 1 : Utiliser une fonction déclenchée par le bouton VALIDER

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    import tkinter as tk
    from tkinter import font
    from tkinter import messagebox
     
    app = tk.Tk()
    app.title('Assistance Humanitaire Internationale')
    app.geometry("1000x500")
     
    # Fonction pour récupérer les données lors du clic sur VALIDER
    def valider_donnees():
        Lenom = entryNom.get()
        Leprenom = entryPrenom.get()
     
        # Vérifier que ce n'est pas le texte par défaut
        if Lenom == "Entrez votre nom ici" or Lenom == "":
            messagebox.showwarning("Attention", "Veuillez entrer un nom valide")
            return
     
        if Leprenom == "Entrez votre prénom ici" or Leprenom == "":
            messagebox.showwarning("Attention", "Veuillez entrer un prénom valide")
            return
     
        # Afficher les données récupérées
        message = f"Bonjour {Lenom} {Leprenom}"
        print(message)
        messagebox.showinfo("Données saisies", message)
     
        # Ici vous pouvez traiter les données (enregistrer dans fichier, base de données, etc.)
     
    # ... (reste de votre code pour les labels) ...
     
    # Création des Entry
    entryNom = tk.Entry(app, width=30)
    entryNom.insert(0, "Entrez votre nom ici")
     
    entryPrenom = tk.Entry(app, width=30)
    entryPrenom.insert(0, "Entrez votre prénom ici")
     
    # ... (autres Entry) ...
     
    # Modifier le bouton VALIDER pour appeler la fonction
    Button0 = tk.Button(app, text="VALIDER", command=valider_donnees)
    Button0.place(x=0, y=450)
     
    app.mainloop()
    Solution 2 : Effacer le texte par défaut au clic

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    # Fonction pour effacer le texte par défaut
    def on_entry_click(event, entry, default_text):
        if entry.get() == default_text:
            entry.delete(0, "end")
            entry.insert(0, '')
     
    def on_focusout(event, entry, default_text):
        if entry.get() == '':
            entry.insert(0, default_text)
     
    # Création de l'Entry avec gestion du focus
    entryNom = tk.Entry(app, width=30)
    entryNom.insert(0, "Entrez votre nom ici")
    entryNom.bind('<FocusIn>', lambda e: on_entry_click(e, entryNom, "Entrez votre nom ici"))
    entryNom.bind('<FocusOut>', lambda e: on_focusout(e, entryNom, "Entrez votre nom ici"))
    Différences importantes entre VBA et Python/Tkinter :

    1. Programmation événementielle
    - VBA : Les UserForms ont des événements automatiques (Click, Change, etc.)
    - Python/Tkinter : Vous devez explicitement lier les fonctions aux événements avec command= ou .bind()

    2. Moment de l'exécution
    - VBA : Le code dans un événement s'exécute quand l'événement se produit
    - Python : Le code s'exécute ligne par ligne lors du lancement du programme

    3. Boucle principale
    - VBA : Gestion automatique de l'interface
    - Python : app.mainloop() est nécessaire pour maintenir la fenêtre ouverte

    Voici un code minimal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    import tkinter as tk
    from tkinter import messagebox
     
    def valider_donnees():
        # Récupération des données AU MOMENT DU CLIC
        nom = entryNom.get()
        prenom = entryPrenom.get()
     
        # Validation simple
        if nom and prenom:
            messagebox.showinfo("Succès", f"Adhérent enregistré : {nom} {prenom}")
            # Effacer les champs après validation
            entryNom.delete(0, tk.END)
            entryPrenom.delete(0, tk.END)
        else:
            messagebox.showwarning("Erreur", "Veuillez remplir tous les champs")
     
    app = tk.Tk()
    app.title('Assistance Humanitaire')
    app.geometry("400x200")
     
    tk.Label(app, text="NOM:").grid(row=0, column=0, padx=10, pady=10)
    entryNom = tk.Entry(app, width=30)
    entryNom.grid(row=0, column=1, padx=10, pady=10)
     
    tk.Label(app, text="PRENOM:").grid(row=1, column=0, padx=10, pady=10)
    entryPrenom = tk.Entry(app, width=30)
    entryPrenom.grid(row=1, column=1, padx=10, pady=10)
     
    tk.Button(app, text="VALIDER", command=valider_donnees).grid(row=2, column=1, pady=20)
     
    app.mainloop()
    Conseil pour votre transition VBA vers Python :

    Pensez toujours en termes d'événements :
    - Création des widgets : se fait au démarrage
    - Récupération des données : se fait dans une fonction liée à un bouton
    - mainloop() : maintient l'application en attente d'événements
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  3. #3
    Invité de passage
    Homme Profil pro
    Retraité
    Inscrit en
    Octobre 2025
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2025
    Messages : 26
    Par défaut
    Un grand MERCI Fred pour ces explications.
    D'abord je ne suis en aucun cas informaticien - analyste - programmeur. Juste un retraité investi dans une assos humanitaire (trésorier) https://www.assistancehumanitaire.org/
    et qui cherche à améliorer notre fonctionnement. J'avais écrit pendant la COVID un chouette programme en VBA qui gérait les adhérents (création, modification, archivage, suppression). Qui gérait toute la comptra et trésorerie, et le suivi des projets. Tout cela fonctionne très bien sur Windows 10 et OFFICE 2007. Sauf que mes collègues passent tous à Windows11 et là bug!
    Donc je nourris le secret espoir de réécrire tout cela en Python. Mais...

    J'ai intégré votre solution et cela marche. reste, après le nom et prénom, à faire tout le reste.
    Ensuite il me faudra trouver le code pour ajouter la ligne saisie dans mon tableur excel. Je pense que cela doit être possible.
    Merci encore de votre aide et restez à l'écoute. Je ne sais pas pourquoi mais j'ai l'impression que je vais encore avoir besoin de vos conseil... Lol
    Yves

  4. #4
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 779
    Par défaut
    Il est important de proposer votre code entre balises (bouton #) car en python, l'indentation est extrêmement importante.

    Il y a deux définitions distinctes pour la fonction valider_donnees() :

    La première (lignes 6 à 17) : Elle effectue une validation simple (if nom and prenom: ), affiche un message de succès, et efface les champs.
    La deuxième (lignes 20 à 35) : Elle effectue une validation contre un texte par défaut ("Entrez votre nom/prénom ici"), affiche les données, et ne vide pas les champs.

    Le Problème : En Python, lorsque le script est exécuté, la dernière définition de la fonction valider_donnees() écrase la précédente.

    Point à éclaircir/Valider : Laquelle des deux logiques de validation est la bonne ?

    Bien que place fonctionne, il est très rigide. Si la fenêtre est redimensionnée (app.geometry("1000x500") est une taille fixe, mais si l'utilisateur l'agrandit), l'interface ne s'adaptera pas et les éléments risquent d'être mal positionnés. Les méthodes .grid() ou .pack() sont généralement préférées pour des formulaires qui doivent être responsive.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  5. #5
    Invité de passage
    Homme Profil pro
    Retraité
    Inscrit en
    Octobre 2025
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2025
    Messages : 26
    Par défaut
    Il suffit de remplacer
    labelTitre2.place(x=400, y=25)
    par
    labelTitre2.pack(x=400, y=25)
    J'ai bien peur que mon raisonnement ne soit un peu simpliste....

  6. #6
    Invité de passage
    Homme Profil pro
    Retraité
    Inscrit en
    Octobre 2025
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2025
    Messages : 26
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    import tkinter as tk
    from tkinter import messagebox
    from tkinter import font
     
    # --- Fonction pour récupérer les données lors du clic sur VALIDER
    def valider_donnees():
        Lenom = entryNom.get()
        Leprenom = entryPrenom.get()
        Ladresse1= entryAdresse1.get()
        Ladresse2= entryAdresse1.get()
        Lecodepostal= entryCpostal.get()
        Laville= entryVille.get() 
        Letelefixe= entryTphfixe.get() 
        Leteleport=entryTphport.get()
        Lemail=entryMail.get()
        Ladhesion=entryAdhesion.get()
        Lanaissance=entryNaissance.get()
        Laprofession=entryProfession.get()
        Lalettre=entryLettre.get()
        Lacotisation=entryCotisation.get()
        Larelance=entryCotisation.get()
     
        # Vérifier que ce n'est pas le texte par défaut
        if Lenom == "Entrez votre nom ici" or Lenom == "":
            messagebox.showwarning("Attention", "Veuillez entrer un nom valide")
            return
     
        if Leprenom == "Entrez votre prénom ici" or Leprenom == "":
            messagebox.showwarning("Attention", "Veuillez entrer un prénom valide")
            return
     
        # Afficher les données récupérées
        message = f"Création de {Lenom} {Leprenom} {Ladresse1} {Lecodepostal} {Laville} {Letelefixe} {Leteleport} {Lemail}"
        messagebox.showinfo("Données saisies", message)
        messagebox.showinfo("Succès", f"Adhérent: {Lenom} {Leprenom} enregistré")
     
        # Ici vous pouvez traiter les données (enregistrer dans fichier, base de données, etc.)
     
        #==================
     
        # Effacer les champs après validation
        entryNom.delete(0, tk.END)
        entryPrenom.delete(0, tk.END)
        entryAdresse1.delete(0, tk.END)
        entryAdresse2.delete(0, tk.END)
        entryCpostal.delete(0, tk.END)
        entryVille.delete(0, tk.END)
        entryTphfixe.delete(0, tk.END)
        entryTphport.delete(0, tk.END)
        entryMail.delete(0, tk.END)
        entryAdhesion.delete(0, tk.END)
        entryNaissance.delete(0, tk.END)
        entryProfession.delete(0, tk.END)
        entryLettre.delete(0, tk.END)
        entryCotisation.delete(0, tk.END)
        entryRelance.delete(0, tk.END)
     
    # fin des fonctions 
     
    # le code
    app = tk.Tk()
    app.title('Assistance Humanitaire Internationale')
    app.geometry("1000x500")
     
    custom_font = font.Font(family="Helvetica", size=16, weight="bold")
    labelTitre1 = tk.Label(app, text="SAISIE ADHERENTS", fg="blue", bg="#FF0", font=custom_font)
    labelTitre1.place(x=400, y=0) #              x = du bord gauche - y= du haut
    labelTitre2 = tk.Label(app, text="--------------------------------------")
    labelTitre2.place(x=400, y=25)
    #-----
    labelNom = tk.Label(app, text="NOM", fg="blue", bg="#FF0")
    labelNom.place(x=0, y=50)
    custom_font = font.Font(family="Helvetica", size=8, weight="bold")
    labelNom2 = tk.Label(app, text="ATTENTION: utiliser le - pour les noms composés", fg="Red", bg="#0ff", font=custom_font)
    labelNom2.place(x=300, y=50)
    labelPrenom = tk.Label(app, text="PRENOM", fg="blue", bg="#FF0")
    labelPrenom.place(x=0, y=75)
    labelPrenom2 = tk.Label(app, text="ATTENTION: utiliser le - pour les prénoms composés", fg="Red", bg="#0ff", font=custom_font)
    labelPrenom2.place(x=300, y=75)
    labelAdresse1 = tk.Label(app, text="Adresse1")
    labelAdresse1.place(x=0, y=100)
    labelAdresse2 = tk.Label(app, text="Adresse2")
    labelAdresse2.place(x=0, y=125)
    labelCpostal = tk.Label(app, text="Code Postal")
    labelCpostal.place(x=0, y=150)
    labelVille = tk.Label(app, text="Ville")
    labelVille.place(x=325, y=150)
    labelTphfixe = tk.Label(app, text="Tph fixe")
    labelTphfixe.place(x=0, y=175)
    labelTphport = tk.Label(app, text="Tph portable")
    labelTphport.place(x=325, y=175)
    labelMail = tk.Label(app, text="Mail")
    labelMail.place(x=0, y=200)
    labelAdhesion = tk.Label(app, text="Année Adhésion")
    labelAdhesion.place(x=700, y=50)
    labelNaissance = tk.Label(app, text="Dete de naissance")
    labelNaissance.place(x=700, y=75)
    labelNaissance2 = tk.Label(app, text="jj/mm/aaaa", fg="Red", bg="#0ff", font=custom_font)
    labelNaissance2.place(x=900, y=75)
    labelProfession = tk.Label(app, text="Profession")
    labelProfession.place(x=700, y=100)
    labelLettre = tk.Label(app, text="Lettre info")
    labelLettre.place(x=700, y=125)
    labelLettre1 = tk.Label(app, text="Tapez O ou N", fg="Red", bg="#0ff")
    labelLettre1.place(x=850, y=125)
    labelCotisation = tk.Label(app, text="Année Cotisation", fg="Red", bg="Yellow")
    labelCotisation.place(x=700, y=150)
    labelRelance = tk.Label(app, text="Relance Cotisation", fg="Red", bg="Yellow")
    labelRelance.place(x=700, y=175)
     
    # Création des Entry
    entryNom = tk.Entry(app, width=30)
    entryNom.insert(0, "Entrez votre nom ici")
    entryPrenom = tk.Entry(app, width=30) #width = longeur zone de saisie = largeur de la colonne
    entryPrenom.insert(0, "Entrez votre prénom ici")
    entryAdresse1 = tk.Entry(app, width=40)
    entryAdresse2 = tk.Entry(app, width=40)
    entryCpostal= tk.Entry(app, width=5)
    entryVille = tk.Entry(app, width=40)
    entryTphfixe = tk.Entry(app, width=12)
    entryTphport = tk.Entry(app, width=12)
    entryMail = tk.Entry(app, width=40)
    entryAdhesion = tk.Entry(app, width=4)
    entryNaissance = tk.Entry(app, width=10)
    entryProfession = tk.Entry(app, width=25)
    entryLettre = tk.Entry(app, width=2)
    entryCotisation = tk.Entry(app, width=4)
    entryRelance = tk.Entry(app, width=2)
     
    # x = du bord gauche - y= du haut
    entryNom.place(x=85, y=50)
    entryPrenom.place(x=85, y=75)
    entryAdresse1.place(x=85, y=100)
    entryAdresse2.place(x=85, y=125)
    entryCpostal.place(x=85, y=150)
    entryVille.place(x=410, y=150)
    entryTphfixe.place(x=85, y=175)
    entryTphport.place(x=410, y=175)
    entryMail.place(x=85, y=200)
    entryAdhesion.place(x=825, y=50)
    entryNaissance.place(x=825, y=75)
    entryProfession.place(x=825, y=100)
    entryLettre.place(x=825, y=125)
    entryCotisation.place(x=825, y=150)
    entryRelance.place(x=825, y=175)
    #----------------------
    Button0=tk.Button(app, text="VALIDER", command = valider_donnees)
    Button0.place(x=5, y=450)
    Button1 = tk.Button(app, text="MODIFIER")
    Button1.place(x=100, y=450)
    Button2 = tk.Button(app, text="SUPPRIMER")
    Button2.place(x=200, y=450)
    Button3 = tk.Button(app, text="QUITTER",command = quit)
    Button3.place(x=500, y=450)
     
    app.mainloop()

  7. #7
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 779
    Par défaut
    J'ai pas tout testé, mais voici le code corrigé,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    import tkinter as tk
    from tkinter import messagebox
    from tkinter import font
    import re
     
     
    # --- Gestion des placeholders ---
    def setup_placeholder(entry, placeholder_text):
        """Configure un placeholder pour un champ Entry"""
        entry.insert(0, placeholder_text)
        entry.config(fg="grey")
     
        def on_focus_in(event):
            if entry.get() == placeholder_text:
                entry.delete(0, tk.END)
                entry.config(fg="black")
     
        def on_focus_out(event):
            if entry.get() == "":
                entry.insert(0, placeholder_text)
                entry.config(fg="grey")
     
        entry.bind("<FocusIn>", on_focus_in)
        entry.bind("<FocusOut>", on_focus_out)
     
     
    # --- Fonctions de validation ---
    def valider_email(email):
        """Valide le format d'un email"""
        pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
        return re.match(pattern, email) is not None
     
     
    def valider_date(date):
        """Valide le format jj/mm/aaaa"""
        pattern = r"^\d{2}/\d{2}/\d{4}$"
        return re.match(pattern, date) is not None
     
     
    def valider_annee(annee):
        """Valide une année (4 chiffres)"""
        return annee.isdigit() and len(annee) == 4
     
     
    # --- Fonction pour récupérer les données lors du clic sur VALIDER ---
    def valider_donnees():
        # 1. Récupération des données
        Lenom = entryNom.get()
        Leprenom = entryPrenom.get()
        Ladresse1 = entryAdresse1.get()
        Ladresse2 = entryAdresse2.get()
        Lecodepostal = entryCpostal.get()
        Laville = entryVille.get()
        Letelefixe = entryTphfixe.get()
        Leteleport = entryTphport.get()
        Lemail = entryMail.get()
        Ladhesion = entryAdhesion.get()
        Lanaissance = entryNaissance.get()
        Laprofession = entryProfession.get()
        Lalettre = entryLettre.get().upper()
        Lacotisation = entryCotisation.get()
        Larelance = entryRelance.get()
     
        # 2. Vérifications
        if Lenom == "Entrez votre nom ici" or Lenom == "":
            messagebox.showwarning("Attention", "Veuillez entrer un nom valide")
            entryNom.focus()
            return
     
        if Leprenom == "Entrez votre prénom ici" or Leprenom == "":
            messagebox.showwarning("Attention", "Veuillez entrer un prénom valide")
            entryPrenom.focus()
            return
     
        if Ladresse1 == "":
            messagebox.showwarning("Attention", "Veuillez entrer une adresse")
            entryAdresse1.focus()
            return
     
        if Lecodepostal == "":
            messagebox.showwarning("Attention", "Veuillez entrer un code postal")
            entryCpostal.focus()
            return
     
        if Laville == "":
            messagebox.showwarning("Attention", "Veuillez entrer une ville")
            entryVille.focus()
            return
     
        if Lemail != "" and not valider_email(Lemail):
            messagebox.showwarning("Attention", "Format d'email invalide")
            entryMail.focus()
            return
     
        if Lanaissance != "" and not valider_date(Lanaissance):
            messagebox.showwarning("Attention", "Format de date invalide (jj/mm/aaaa)")
            entryNaissance.focus()
            return
     
        if Ladhesion != "" and not valider_annee(Ladhesion):
            messagebox.showwarning("Attention", "Année d'adhésion invalide (4 chiffres)")
            entryAdhesion.focus()
            return
     
        if Lacotisation != "" and not valider_annee(Lacotisation):
            messagebox.showwarning("Attention", "Année de cotisation invalide (4 chiffres)")
            entryCotisation.focus()
            return
     
        if Lalettre != "" and Lalettre not in ["O", "N"]:
            messagebox.showwarning("Attention", "Lettre info doit être O ou N")
            entryLettre.focus()
            return
     
        # 3. Afficher les données récupérées
        message = (
            f"Création de {Lenom} {Leprenom}\n"
            f"Adresse 1: {Ladresse1}\n"
            f"Adresse 2: {Ladresse2}\n"
            f"CP/Ville: {Lecodepostal} {Laville}\n"
            f"Fixe/Port: {Letelefixe} / {Leteleport}\n"
            f"Mail: {Lemail}\n"
            f"Adhésion: {Ladhesion}, Naissance: {Lanaissance}, Profession: {Laprofession}\n"
            f"Lettre: {Lalettre}, Cotisation: {Lacotisation}, Relance: {Larelance}"
        )
        messagebox.showinfo("Données saisies", message)
        messagebox.showinfo(
            "Succès", f"Adhérent: {Lenom} {Leprenom} enregistré avec succès."
        )
     
        # 4. Effacer les champs après validation
        effacer_formulaire()
     
     
    def effacer_formulaire():
        """Efface tous les champs du formulaire"""
        entryNom.delete(0, tk.END)
        entryPrenom.delete(0, tk.END)
        entryAdresse1.delete(0, tk.END)
        entryAdresse2.delete(0, tk.END)
        entryCpostal.delete(0, tk.END)
        entryVille.delete(0, tk.END)
        entryTphfixe.delete(0, tk.END)
        entryTphport.delete(0, tk.END)
        entryMail.delete(0, tk.END)
        entryAdhesion.delete(0, tk.END)
        entryNaissance.delete(0, tk.END)
        entryProfession.delete(0, tk.END)
        entryLettre.delete(0, tk.END)
        entryCotisation.delete(0, tk.END)
        entryRelance.delete(0, tk.END)
     
        # Réinitialiser les placeholders
        setup_placeholder(entryNom, "Entrez votre nom ici")
        setup_placeholder(entryPrenom, "Entrez votre prénom ici")
     
     
    def modifier_donnees():
        """Fonction pour modifier un adhérent (à implémenter)"""
        messagebox.showinfo("Modifier", "Fonction MODIFIER à implémenter")
     
     
    def supprimer_donnees():
        """Fonction pour supprimer un adhérent"""
        reponse = messagebox.askyesno(
            "Confirmation", "Voulez-vous vraiment supprimer cet adhérent ?"
        )
        if reponse:
            effacer_formulaire()
            messagebox.showinfo("Suppression", "Adhérent supprimé")
     
    # Fonction helper pour créer des lignes
    def create_row(parent_frame, label_text, entry_width, tip_text=None, tip_fg="Red"):
        row_frame = tk.Frame(parent_frame)
        row_frame.pack(fill="x", pady=2, anchor="w")
     
        label = tk.Label(row_frame, text=label_text, width=15, anchor="w")
        label.pack(side="left")
     
        entry = tk.Entry(row_frame, width=entry_width)
        entry.pack(side="left")
     
        if tip_text:
            tip_label = tk.Label(row_frame, text=tip_text, fg=tip_fg, font=small_red_font)
            tip_label.pack(side="left", padx=5)
        return entry
     
    # ----------------- Configuration de la fenêtre et des polices -----------------
    app = tk.Tk()
    app.title("Assistance Humanitaire Internationale")
     
    custom_font = font.Font(family="Helvetica", size=16, weight="bold")
    small_red_font = font.Font(family="Helvetica", size=8, weight="bold")
     
    # ----------------- 1. Titre (en haut) -----------------
    labelTitre1 = tk.Label(
        app, text="SAISIE ADHERENTS", fg="blue", bg="#FF0", font=custom_font
    )
    labelTitre1.pack(side="top", pady=10)
    labelTitre2 = tk.Label(app, text="--------------------------------------")
    labelTitre2.pack(side="top", pady=(0, 10))
     
    # ----------------- 2. Conteneur principal pour les deux colonnes -----------------
    main_frame = tk.Frame(app)
    main_frame.pack(fill="x", padx=10)
     
    # ----------------- 2a. Frame de Gauche (Coordonnées) -----------------
    frameGauche = tk.Frame(main_frame)
    frameGauche.pack(side="left", padx=10, anchor="n")
     
    # Widgets de Gauche
    entryNom = create_row(
        frameGauche, "NOM", 30, tip_text="ATTENTION: utiliser le - pour les noms composés"
    )
    setup_placeholder(entryNom, "Entrez votre nom ici")
     
    entryPrenom = create_row(
        frameGauche,
        "PRENOM",
        30,
        tip_text="ATTENTION: utiliser le - pour les prénoms composés",
    )
    setup_placeholder(entryPrenom, "Entrez votre prénom ici")
     
    entryAdresse1 = create_row(frameGauche, "Adresse 1", 40)
    entryAdresse2 = create_row(frameGauche, "Adresse 2", 40)
     
    # Code Postal et Ville
    row_cp_ville = tk.Frame(frameGauche)
    row_cp_ville.pack(fill="x", pady=2, anchor="w")
    tk.Label(row_cp_ville, text="Code Postal", width=15, anchor="w").pack(side="left")
    entryCpostal = tk.Entry(row_cp_ville, width=5)
    entryCpostal.pack(side="left")
    tk.Label(row_cp_ville, text="Ville", width=5, anchor="w").pack(
        side="left", padx=(20, 0)
    )
    entryVille = tk.Entry(row_cp_ville, width=30)
    entryVille.pack(side="left")
     
    # Téléphones
    row_tph = tk.Frame(frameGauche)
    row_tph.pack(fill="x", pady=2, anchor="w")
    tk.Label(row_tph, text="Tph fixe", width=15, anchor="w").pack(side="left")
    entryTphfixe = tk.Entry(row_tph, width=12)
    entryTphfixe.pack(side="left")
    tk.Label(row_tph, text="Tph portable", width=15, anchor="w").pack(
        side="left", padx=(20, 0)
    )
    entryTphport = tk.Entry(row_tph, width=12)
    entryTphport.pack(side="left")
     
    # Mail
    entryMail = create_row(frameGauche, "Mail", 40)
     
    # ----------------- 2b. Frame de Droite (Adhésion) -----------------
    frameDroite = tk.Frame(main_frame)
    frameDroite.pack(side="left", padx=30, anchor="n")
     
    # Widgets de Droite
    entryAdhesion = create_row(frameDroite, "Année Adhésion", 4)
    entryNaissance = create_row(
        frameDroite, "Date de naissance", 10, tip_text="jj/mm/aaaa", tip_fg="Red"
    )
    entryProfession = create_row(frameDroite, "Profession", 25)
    entryLettre = create_row(
        frameDroite, "Lettre info", 2, tip_text="Tapez O ou N", tip_fg="Red"
    )
    entryCotisation = create_row(frameDroite, "Année Cotisation", 4)
    entryRelance = create_row(frameDroite, "Relance Cotisation", 2)
     
    # ----------------- 3. Frame des Boutons (en bas) -----------------
    frameBoutons = tk.Frame(app, pady=20)
    frameBoutons.pack(side="bottom", fill="x")
     
    # Boutons
    Button0 = tk.Button(
        frameBoutons, text="VALIDER", command=valider_donnees, bg="#90EE90", width=10
    )
    Button0.pack(side="left", padx=10)
    Button1 = tk.Button(frameBoutons, text="MODIFIER", command=modifier_donnees, width=10)
    Button1.pack(side="left", padx=10)
    Button2 = tk.Button(
        frameBoutons, text="SUPPRIMER", command=supprimer_donnees, bg="#FFB6C1", width=10
    )
    Button2.pack(side="left", padx=10)
    Button3 = tk.Button(frameBoutons, text="QUITTER", command=app.quit, width=10)
    Button3.pack(side="right", padx=10)
     
    app.mainloop()
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  8. #8
    Invité de passage
    Homme Profil pro
    Retraité
    Inscrit en
    Octobre 2025
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2025
    Messages : 26
    Par défaut
    Oh là là! Vraiment merci de consacrer du temps à "mon œuvre" ! A.H.I avance grâce à vous...
    C'est vraiment sympa.
    La prochaine étape sera pour moi de pouvoir, à la saisie du nom et prénom, vérifier si une fiche n'existe pas déjà, puis éventuellement la modifier et l'enregistrer. Dans ce cas là le bouton "valider" devrait être inactif, seul "Modifier" serait actif avec "Quitter" bien sûr.

    En attendant je vais regarder votre super boulot et apprendre dessus. C'est avec de tels exemples que j'arrive peu à peu à comprendre.
    MERCI encore Fred.
    PS: restez à l'écoute et un bonjour de Béziers.

  9. #9
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 779
    Par défaut
    L'IA a beaucoup aidé pour générer rapidement, j'ai un peu remis en ordre, mais je vois des mauvaises pratiques comme des fonctions dans des fonctions, les conditions qui devraient être dans des fonctions de validation, et surtout améliorer l'architecture (pour l'instant tout se trouve dans un seul fichier) afin de séparer les responsabilités.

    Faut surtout voir si il va y avoir une évolution importante sur cette interface qui est prévue...
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  10. #10
    Invité de passage
    Homme Profil pro
    Retraité
    Inscrit en
    Octobre 2025
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2025
    Messages : 26
    Par défaut
    Au secours.

    Erreur à l'exécution dans ce passage...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
      messagebox.showinfo("Données saisies", message)
        messagebox.showinfo(
            "Succès", f"Adhérent: {Lenom} {Leprenom} enregistré avec succès."
        )
     
        # 4. Effacer les champs après validation
    	effacer_formulaire()
     
     
    def effacer_formulaire():
        """Efface tous les champs du formulaire"""
        entryCivilite.delete(0, tk.END)
        entryNom.delete(0, tk.END)
        entryPrenom.delete(0, tk.END)
        entryAdresse1.delete(0, tk.END)
        entryAdresse2.delete(0, tk.END)
        entryCpostal.delete(0, tk.END)
        entryVille.delete(0, tk.END)
        entryNation.delete(0, tk.END)
        entryTphfixe.delete(0, tk.END)
        entryTphport.delete(0, tk.END)
        entryMail.delete(0, tk.END)
        entryAdhesion.delete(0, tk.END)
        entryNaissance.delete(0, tk.END)
        entryProfession.delete(0, tk.END)
        entryLettre.delete(0, tk.END)
        entryCotisation.delete(0, tk.END)
        entryRelance.delete(0, tk.END)
        entryStatut.delete(0, tk.END)
        entryObserv.delete(0, tk.END)
     
        # Réinitialiser les placeholders
        setup_placeholder(entryNom, "Entrez votre nom ici")
        setup_placeholder(entryPrenom, "Entrez votre prénom ici")

    File "D:\Documents de YVES\Programmation informatique\PYTHON\Essai1.py", line 141
    effacer_formulaire()
    ^
    TabError: inconsistent use of tabs and spaces in indentation


    ------------------
    (program exited with code: 1)

    Appuyez sur une touche pour continuer...

    Pourtant je n'ai fait qu'ajouter des infos supplémentaires.
    Ca a fonctionné pourtant...

    Ensuite, je voudrais placer un bouton "Envoyer un mail" juste en dessous du champ "Adresse mail"
    Avec place jy suis arrivé mais là ... ?

    Nom : Ecran 1.jpg
Affichages : 265
Taille : 446,1 KoNom : Ecran 1.jpg
Affichages : 265
Taille : 446,1 Ko

    Merci de ton aide.

  11. #11
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 779
    Par défaut
    Ce n'est pas une erreur de ma part mais de la vôtre, ou plutôt, vous utilisez un IDE où vous ne réglez pas l'équivalence de la touche <TAB> comme valant 4 espaces.

    Du coup votre IDE y voit une incohérence...

    Il faut donc choisir, mais en ce qui concerne quasi 100% des développeurs pro, <TAB> vaut 4 espaces

    Par ex. sur mon IDE, j'ai ceci en bas à droite

    Nom : Copie d'écran_20251030_104401.png
Affichages : 161
Taille : 5,5 Ko

    Notez le Spaces: 4

    EDIT: Pour vérifier, créez un nouveau fichier python et copier coller mon code entièrement, vous n'aurez plus de problème d'incohérence dans l'indentation.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  12. #12
    Invité de passage
    Homme Profil pro
    Retraité
    Inscrit en
    Octobre 2025
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2025
    Messages : 26
    Par défaut
    Apparemment si en bas chaque tabulation avance de 4 colonne et la ligne 141 est bien à 4 colonnes

  13. #13
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 779
    Par défaut
    J'ai testé le code chez moi tout est fonctionnel
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  14. #14
    Invité de passage
    Homme Profil pro
    Retraité
    Inscrit en
    Octobre 2025
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2025
    Messages : 26
    Par défaut
    J'ai fait comme vous m'avez dit copie collé de cette partie du message " et ça fonctionne à nouveau.
    Merci de votre patience.

  15. #15
    Invité de passage
    Homme Profil pro
    Retraité
    Inscrit en
    Octobre 2025
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2025
    Messages : 26
    Par défaut
    Re-bonjour,
    je voudrais suivant vos modèles faire un contrôle de validité sur les numéros de téléphone.
    J'ai mis ce code mais rien ne passe !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #def valider_tph(telephone):
    #	"""Valide les n° téléphone avec . """
    #	pattern = r"^(\d{3})-(\d{3})-(\d{4})$'"
    #	return re.match(pattern, telephone) is not None
    #	return telephone.isdigit() and len(telephone) == 14
    Pourriez-vous m'éclairer.
    Merci

  16. #16
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 779
    Par défaut
    Quel format de téléphone voulez-vous accepter ?
    Format français classique (01 23 45 67 89) ?
    Avec ou sans espaces/points/tirets ?
    Avec indicatif international (+33) ?
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  17. #17
    Invité de passage
    Homme Profil pro
    Retraité
    Inscrit en
    Octobre 2025
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2025
    Messages : 26
    Par défaut
    classique avec espace et avec indicatif 0033
    car nous avons des adhérents en Belgique 0032
    et en Espagne 0034

    PS: j'ai réussi à mettre une image (logo) dans mon menu... Yessss!

  18. #18
    Invité de passage
    Homme Profil pro
    Retraité
    Inscrit en
    Octobre 2025
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2025
    Messages : 26
    Par défaut
    Nom : Sans titre 1.jpg
Affichages : 148
Taille : 323,9 Ko

  19. #19
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 779
    Par défaut
    Voici une fonction que je propose,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    def valider_telephone(telephone):
        """Valide le format d'un numéro de téléphone (FR, BE, ES)"""
        if telephone == "":  # Champ optionnel
            return True
     
        # Retirer les espaces pour la validation
        tel_clean = telephone.replace(" ", "")
     
        # Format avec indicatif international: 0033, 0032, 0034
        # France: 0033 1 23 45 67 89 (11 chiffres après nettoyage)
        # Belgique: 0032 4 12 34 56 78 (11 chiffres)
        # Espagne: 0034 6 12 34 56 78 (11 chiffres)
        pattern_international = r"^00(33|32|34)[1-9]\d{8}$"
     
        # Format national français: 01 23 45 67 89 (10 chiffres)
        pattern_national = r"^0[1-9]\d{8}$"
     
        return re.match(pattern_international, tel_clean) or re.match(pattern_national, tel_clean)

    Ajoutez ensuite ces validations dans valider_donnees()

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    if Letelefixe != "" and not valider_telephone(Letelefixe):
            messagebox.showwarning(
                "Attention", 
                "Format de téléphone fixe invalide\n"
                "Exemples acceptés:\n"
                "- National: 01 23 45 67 89\n"
                "- International: 0033 1 23 45 67 89 (France)\n"
                "                0032 4 12 34 56 78 (Belgique)\n"
                "                0034 6 12 34 56 78 (Espagne)"
            )
            entryTphfixe.focus()
            return
     
        if Leteleport != "" and not valider_telephone(Leteleport):
            messagebox.showwarning(
                "Attention", 
                "Format de téléphone portable invalide\n"
                "Exemples acceptés:\n"
                "- National: 06 12 34 56 78\n"
                "- International: 0033 6 12 34 56 78 (France)\n"
                "                0032 4 12 34 56 78 (Belgique)\n"
                "                0034 6 12 34 56 78 (Espagne)"
            )
            entryTphport.focus()
            return
    Chez moi étant que j'ai pas votre code à jour ça donne ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    import tkinter as tk
    from tkinter import messagebox
    from tkinter import font
    import re
     
     
    # --- Gestion des placeholders ---
    def setup_placeholder(entry, placeholder_text):
        """Configure un placeholder pour un champ Entry"""
        entry.insert(0, placeholder_text)
        entry.config(fg="grey")
     
        def on_focus_in(event):
            if entry.get() == placeholder_text:
                entry.delete(0, tk.END)
                entry.config(fg="black")
     
        def on_focus_out(event):
            if entry.get() == "":
                entry.insert(0, placeholder_text)
                entry.config(fg="grey")
     
        entry.bind("<FocusIn>", on_focus_in)
        entry.bind("<FocusOut>", on_focus_out)
     
     
    # --- Fonctions de validation ---
    def valider_email(email):
        """Valide le format d'un email"""
        pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
        return re.match(pattern, email) is not None
     
     
    def valider_date(date):
        """Valide le format jj/mm/aaaa"""
        pattern = r"^\d{2}/\d{2}/\d{4}$"
        return re.match(pattern, date) is not None
     
     
    def valider_annee(annee):
        """Valide une année (4 chiffres)"""
        return annee.isdigit() and len(annee) == 4
     
     
    def valider_telephone(telephone):
        """Valide le format d'un numéro de téléphone (FR, BE, ES)"""
        if telephone == "":  # Champ optionnel
            return True
     
        # Retirer les espaces pour la validation
        tel_clean = telephone.replace(" ", "")
     
        # Format avec indicatif international: 0033, 0032, 0034
        # France: 0033 1 23 45 67 89 (11 chiffres après nettoyage)
        # Belgique: 0032 4 12 34 56 78 (11 chiffres)
        # Espagne: 0034 6 12 34 56 78 (11 chiffres)
        pattern_international = r"^00(33|32|34)[1-9]\d{8}$"
     
        # Format national français: 01 23 45 67 89 (10 chiffres)
        pattern_national = r"^0[1-9]\d{8}$"
     
        return re.match(pattern_international, tel_clean) or re.match(
            pattern_national, tel_clean
        )
     
     
    # --- Fonction pour récupérer les données lors du clic sur VALIDER ---
    def valider_donnees():
        # 1. Récupération des données
        Lenom = entryNom.get()
        Leprenom = entryPrenom.get()
        Ladresse1 = entryAdresse1.get()
        Ladresse2 = entryAdresse2.get()
        Lecodepostal = entryCpostal.get()
        Laville = entryVille.get()
        Letelefixe = entryTphfixe.get()
        Leteleport = entryTphport.get()
        Lemail = entryMail.get()
        Ladhesion = entryAdhesion.get()
        Lanaissance = entryNaissance.get()
        Laprofession = entryProfession.get()
        Lalettre = entryLettre.get().upper()
        Lacotisation = entryCotisation.get()
        Larelance = entryRelance.get()
     
        # 2. Vérifications
        if Lenom == "Entrez votre nom ici" or Lenom == "":
            messagebox.showwarning("Attention", "Veuillez entrer un nom valide")
            entryNom.focus()
            return
     
        if Leprenom == "Entrez votre prénom ici" or Leprenom == "":
            messagebox.showwarning("Attention", "Veuillez entrer un prénom valide")
            entryPrenom.focus()
            return
     
        if Ladresse1 == "":
            messagebox.showwarning("Attention", "Veuillez entrer une adresse")
            entryAdresse1.focus()
            return
     
        if Lecodepostal == "":
            messagebox.showwarning("Attention", "Veuillez entrer un code postal")
            entryCpostal.focus()
            return
     
        if Laville == "":
            messagebox.showwarning("Attention", "Veuillez entrer une ville")
            entryVille.focus()
            return
     
        if Lemail != "" and not valider_email(Lemail):
            messagebox.showwarning("Attention", "Format d'email invalide")
            entryMail.focus()
            return
     
        if Lanaissance != "" and not valider_date(Lanaissance):
            messagebox.showwarning("Attention", "Format de date invalide (jj/mm/aaaa)")
            entryNaissance.focus()
            return
     
        if Ladhesion != "" and not valider_annee(Ladhesion):
            messagebox.showwarning("Attention", "Année d'adhésion invalide (4 chiffres)")
            entryAdhesion.focus()
            return
     
        if Lacotisation != "" and not valider_annee(Lacotisation):
            messagebox.showwarning("Attention", "Année de cotisation invalide (4 chiffres)")
            entryCotisation.focus()
            return
     
        if Lalettre != "" and Lalettre not in ["O", "N"]:
            messagebox.showwarning("Attention", "Lettre info doit être O ou N")
            entryLettre.focus()
            return
     
        if Letelefixe != "" and not valider_telephone(Letelefixe):
            messagebox.showwarning(
                "Attention",
                "Format de téléphone fixe invalide\n"
                "Exemples acceptés:\n"
                "- National: 01 23 45 67 89\n"
                "- International: 0033 1 23 45 67 89 (France)\n"
                "                0032 4 12 34 56 78 (Belgique)\n"
                "                0034 6 12 34 56 78 (Espagne)",
            )
            entryTphfixe.focus()
            return
     
        if Leteleport != "" and not valider_telephone(Leteleport):
            messagebox.showwarning(
                "Attention",
                "Format de téléphone portable invalide\n"
                "Exemples acceptés:\n"
                "- National: 06 12 34 56 78\n"
                "- International: 0033 6 12 34 56 78 (France)\n"
                "                0032 4 12 34 56 78 (Belgique)\n"
                "                0034 6 12 34 56 78 (Espagne)",
            )
            entryTphport.focus()
            return
     
        # 3. Afficher les données récupérées
        message = (
            f"Création de {Lenom} {Leprenom}\n"
            f"Adresse 1: {Ladresse1}\n"
            f"Adresse 2: {Ladresse2}\n"
            f"CP/Ville: {Lecodepostal} {Laville}\n"
            f"Fixe/Port: {Letelefixe} / {Leteleport}\n"
            f"Mail: {Lemail}\n"
            f"Adhésion: {Ladhesion}, Naissance: {Lanaissance}, Profession: {Laprofession}\n"
            f"Lettre: {Lalettre}, Cotisation: {Lacotisation}, Relance: {Larelance}"
        )
        messagebox.showinfo("Données saisies", message)
        messagebox.showinfo(
            "Succès", f"Adhérent: {Lenom} {Leprenom} enregistré avec succès."
        )
     
        # 4. Effacer les champs après validation
        effacer_formulaire()
     
     
    def effacer_formulaire():
        """Efface tous les champs du formulaire"""
        entryNom.delete(0, tk.END)
        entryPrenom.delete(0, tk.END)
        entryAdresse1.delete(0, tk.END)
        entryAdresse2.delete(0, tk.END)
        entryCpostal.delete(0, tk.END)
        entryVille.delete(0, tk.END)
        entryTphfixe.delete(0, tk.END)
        entryTphport.delete(0, tk.END)
        entryMail.delete(0, tk.END)
        entryAdhesion.delete(0, tk.END)
        entryNaissance.delete(0, tk.END)
        entryProfession.delete(0, tk.END)
        entryLettre.delete(0, tk.END)
        entryCotisation.delete(0, tk.END)
        entryRelance.delete(0, tk.END)
     
        # Réinitialiser les placeholders
        setup_placeholder(entryNom, "Entrez votre nom ici")
        setup_placeholder(entryPrenom, "Entrez votre prénom ici")
     
     
    def modifier_donnees():
        """Fonction pour modifier un adhérent (à implémenter)"""
        messagebox.showinfo("Modifier", "Fonction MODIFIER à implémenter")
     
     
    def supprimer_donnees():
        """Fonction pour supprimer un adhérent"""
        reponse = messagebox.askyesno(
            "Confirmation", "Voulez-vous vraiment supprimer cet adhérent ?"
        )
        if reponse:
            effacer_formulaire()
            messagebox.showinfo("Suppression", "Adhérent supprimé")
     
     
    # Fonction helper pour créer des lignes
    def create_row(parent_frame, label_text, entry_width, tip_text=None, tip_fg="Red"):
        row_frame = tk.Frame(parent_frame)
        row_frame.pack(fill="x", pady=2, anchor="w")
     
        label = tk.Label(row_frame, text=label_text, width=15, anchor="w")
        label.pack(side="left")
     
        entry = tk.Entry(row_frame, width=entry_width)
        entry.pack(side="left")
     
        if tip_text:
            tip_label = tk.Label(row_frame, text=tip_text, fg=tip_fg, font=small_red_font)
            tip_label.pack(side="left", padx=5)
        return entry
     
     
    # ----------------- Configuration de la fenêtre et des polices -----------------
    app = tk.Tk()
    app.title("Assistance Humanitaire Internationale")
     
    custom_font = font.Font(family="Helvetica", size=16, weight="bold")
    small_red_font = font.Font(family="Helvetica", size=8, weight="bold")
     
    # ----------------- 1. Titre (en haut) -----------------
    labelTitre1 = tk.Label(
        app, text="SAISIE ADHERENTS", fg="blue", bg="#FF0", font=custom_font
    )
    labelTitre1.pack(side="top", pady=10)
    labelTitre2 = tk.Label(app, text="--------------------------------------")
    labelTitre2.pack(side="top", pady=(0, 10))
     
    # ----------------- 2. Conteneur principal pour les deux colonnes -----------------
    main_frame = tk.Frame(app)
    main_frame.pack(fill="x", padx=10)
     
    # ----------------- 2a. Frame de Gauche (Coordonnées) -----------------
    frameGauche = tk.Frame(main_frame)
    frameGauche.pack(side="left", padx=10, anchor="n")
     
    # Widgets de Gauche
    entryNom = create_row(
        frameGauche, "NOM", 30, tip_text="ATTENTION: utiliser le - pour les noms composés"
    )
    setup_placeholder(entryNom, "Entrez votre nom ici")
     
    entryPrenom = create_row(
        frameGauche,
        "PRENOM",
        30,
        tip_text="ATTENTION: utiliser le - pour les prénoms composés",
    )
    setup_placeholder(entryPrenom, "Entrez votre prénom ici")
     
    entryAdresse1 = create_row(frameGauche, "Adresse 1", 40)
    entryAdresse2 = create_row(frameGauche, "Adresse 2", 40)
     
    # Code Postal et Ville
    row_cp_ville = tk.Frame(frameGauche)
    row_cp_ville.pack(fill="x", pady=2, anchor="w")
    tk.Label(row_cp_ville, text="Code Postal", width=15, anchor="w").pack(side="left")
    entryCpostal = tk.Entry(row_cp_ville, width=5)
    entryCpostal.pack(side="left")
    tk.Label(row_cp_ville, text="Ville", width=5, anchor="w").pack(
        side="left", padx=(20, 0)
    )
    entryVille = tk.Entry(row_cp_ville, width=30)
    entryVille.pack(side="left")
     
    # Téléphones
    row_tph = tk.Frame(frameGauche)
    row_tph.pack(fill="x", pady=2, anchor="w")
    tk.Label(row_tph, text="Tph fixe", width=15, anchor="w").pack(side="left")
    entryTphfixe = tk.Entry(row_tph, width=12)
    entryTphfixe.pack(side="left")
    tk.Label(row_tph, text="Tph portable", width=15, anchor="w").pack(
        side="left", padx=(20, 0)
    )
    entryTphport = tk.Entry(row_tph, width=12)
    entryTphport.pack(side="left")
     
    # Mail
    entryMail = create_row(frameGauche, "Mail", 40)
     
    # ----------------- 2b. Frame de Droite (Adhésion) -----------------
    frameDroite = tk.Frame(main_frame)
    frameDroite.pack(side="left", padx=30, anchor="n")
     
    # Widgets de Droite
    entryAdhesion = create_row(frameDroite, "Année Adhésion", 4)
    entryNaissance = create_row(
        frameDroite, "Date de naissance", 10, tip_text="jj/mm/aaaa", tip_fg="Red"
    )
    entryProfession = create_row(frameDroite, "Profession", 25)
    entryLettre = create_row(
        frameDroite, "Lettre info", 2, tip_text="Tapez O ou N", tip_fg="Red"
    )
    entryCotisation = create_row(frameDroite, "Année Cotisation", 4)
    entryRelance = create_row(frameDroite, "Relance Cotisation", 2)
     
    # ----------------- 3. Frame des Boutons (en bas) -----------------
    frameBoutons = tk.Frame(app, pady=20)
    frameBoutons.pack(side="bottom", fill="x")
     
    # Boutons
    Button0 = tk.Button(
        frameBoutons, text="VALIDER", command=valider_donnees, bg="#90EE90", width=10
    )
    Button0.pack(side="left", padx=10)
    Button1 = tk.Button(frameBoutons, text="MODIFIER", command=modifier_donnees, width=10)
    Button1.pack(side="left", padx=10)
    Button2 = tk.Button(
        frameBoutons, text="SUPPRIMER", command=supprimer_donnees, bg="#FFB6C1", width=10
    )
    Button2.pack(side="left", padx=10)
    Button3 = tk.Button(frameBoutons, text="QUITTER", command=app.quit, width=10)
    Button3.pack(side="right", padx=10)
     
    app.mainloop()
    Plus qu'à tester si tout se valide correctement, y compris ce qui ne se valide pas...
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  20. #20
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 779
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 779
    Par défaut
    Après c'est pas parce qu'on utilise tkinter qu'on ne peut pas faire des interfaces sympas

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    import tkinter as tk
    from tkinter import messagebox
    from tkinter import font
    import re
     
     
    # --- Gestion des placeholders ---
    def setup_placeholder(entry, placeholder_text):
        """Configure un placeholder pour un champ Entry"""
        entry.insert(0, placeholder_text)
        entry.config(fg="grey")
     
        def on_focus_in(event):
            if entry.get() == placeholder_text:
                entry.delete(0, tk.END)
                entry.config(fg="black")
     
        def on_focus_out(event):
            if entry.get() == "":
                entry.insert(0, placeholder_text)
                entry.config(fg="grey")
     
        entry.bind("<FocusIn>", on_focus_in)
        entry.bind("<FocusOut>", on_focus_out)
     
     
    # --- Fonctions de validation ---
    def valider_email(email):
        """Valide le format d'un email"""
        pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
        return re.match(pattern, email) is not None
     
     
    def valider_telephone(telephone):
        """Valide le format d'un numéro de téléphone (FR, BE, ES)"""
        if telephone == "":  # Champ optionnel
            return True
     
        # Retirer les espaces pour la validation
        tel_clean = telephone.replace(" ", "")
     
        # Format avec indicatif international: 0033, 0032, 0034
        # France: 0033 1 23 45 67 89 (11 chiffres après nettoyage)
        # Belgique: 0032 4 12 34 56 78 (11 chiffres)
        # Espagne: 0034 6 12 34 56 78 (11 chiffres)
        pattern_international = r"^00(33|32|34)[1-9]\d{8}$"
     
        # Format national français: 01 23 45 67 89 (10 chiffres)
        pattern_national = r"^0[1-9]\d{8}$"
     
        return re.match(pattern_international, tel_clean) or re.match(pattern_national, tel_clean)
     
     
    def valider_date(date):
        """Valide le format jj/mm/aaaa"""
        pattern = r"^\d{2}/\d{2}/\d{4}$"
        return re.match(pattern, date) is not None
     
     
    def valider_annee(annee):
        """Valide une année (4 chiffres)"""
        return annee.isdigit() and len(annee) == 4
     
     
    # --- Fonction pour récupérer les données lors du clic sur VALIDER ---
    def valider_donnees():
        # 1. Récupération des données
        Lenom = entryNom.get()
        Leprenom = entryPrenom.get()
        Ladresse1 = entryAdresse1.get()
        Ladresse2 = entryAdresse2.get()
        Lecodepostal = entryCpostal.get()
        Laville = entryVille.get()
        Letelefixe = entryTphfixe.get()
        Leteleport = entryTphport.get()
        Lemail = entryMail.get()
        Ladhesion = entryAdhesion.get()
        Lanaissance = entryNaissance.get()
        Laprofession = entryProfession.get()
        Lalettre = entryLettre.get().upper()
        Lacotisation = entryCotisation.get()
        Larelance = entryRelance.get()
     
        # 2. Vérifications
        if Lenom == "Entrez votre nom ici" or Lenom == "":
            messagebox.showwarning("Attention", "Veuillez entrer un nom valide")
            entryNom.focus()
            return
     
        if Leprenom == "Entrez votre prénom ici" or Leprenom == "":
            messagebox.showwarning("Attention", "Veuillez entrer un prénom valide")
            entryPrenom.focus()
            return
     
        if Ladresse1 == "":
            messagebox.showwarning("Attention", "Veuillez entrer une adresse")
            entryAdresse1.focus()
            return
     
        if Lecodepostal == "":
            messagebox.showwarning("Attention", "Veuillez entrer un code postal")
            entryCpostal.focus()
            return
     
        if Laville == "":
            messagebox.showwarning("Attention", "Veuillez entrer une ville")
            entryVille.focus()
            return
     
        if Lemail != "" and not valider_email(Lemail):
            messagebox.showwarning("Attention", "Format d'email invalide")
            entryMail.focus()
            return
     
        # Validation des téléphones
        if Letelefixe != "" and not valider_telephone(Letelefixe):
            messagebox.showwarning(
                "Attention", 
                "Format de téléphone fixe invalide\n\n"
                "Exemples acceptés:\n"
                "• National: 01 23 45 67 89\n"
                "• International:\n"
                "  - France: 0033 1 23 45 67 89\n"
                "  - Belgique: 0032 4 12 34 56 78\n"
                "  - Espagne: 0034 6 12 34 56 78"
            )
            entryTphfixe.focus()
            return
     
        if Leteleport != "" and not valider_telephone(Leteleport):
            messagebox.showwarning(
                "Attention", 
                "Format de téléphone portable invalide\n\n"
                "Exemples acceptés:\n"
                "• National: 06 12 34 56 78\n"
                "• International:\n"
                "  - France: 0033 6 12 34 56 78\n"
                "  - Belgique: 0032 4 12 34 56 78\n"
                "  - Espagne: 0034 6 12 34 56 78"
            )
            entryTphport.focus()
            return
     
        if Lanaissance != "" and not valider_date(Lanaissance):
            messagebox.showwarning("Attention", "Format de date invalide (jj/mm/aaaa)")
            entryNaissance.focus()
            return
     
        if Ladhesion != "" and not valider_annee(Ladhesion):
            messagebox.showwarning("Attention", "Année d'adhésion invalide (4 chiffres)")
            entryAdhesion.focus()
            return
     
        if Lacotisation != "" and not valider_annee(Lacotisation):
            messagebox.showwarning("Attention", "Année de cotisation invalide (4 chiffres)")
            entryCotisation.focus()
            return
     
        if Lalettre != "" and Lalettre not in ["O", "N"]:
            messagebox.showwarning("Attention", "Lettre info doit être O ou N")
            entryLettre.focus()
            return
     
        # 3. Afficher les données récupérées
        message = (
            f"Création de {Lenom} {Leprenom}\n"
            f"Adresse 1: {Ladresse1}\n"
            f"Adresse 2: {Ladresse2}\n"
            f"CP/Ville: {Lecodepostal} {Laville}\n"
            f"Fixe/Port: {Letelefixe} / {Leteleport}\n"
            f"Mail: {Lemail}\n"
            f"Adhésion: {Ladhesion}, Naissance: {Lanaissance}, Profession: {Laprofession}\n"
            f"Lettre: {Lalettre}, Cotisation: {Lacotisation}, Relance: {Larelance}"
        )
        messagebox.showinfo("Données saisies", message)
        messagebox.showinfo(
            "Succès", f"Adhérent: {Lenom} {Leprenom} enregistré avec succès."
        )
     
        # 4. Effacer les champs après validation
        effacer_formulaire()
     
     
    def effacer_formulaire():
        """Efface tous les champs du formulaire"""
        entryNom.delete(0, tk.END)
        entryPrenom.delete(0, tk.END)
        entryAdresse1.delete(0, tk.END)
        entryAdresse2.delete(0, tk.END)
        entryCpostal.delete(0, tk.END)
        entryVille.delete(0, tk.END)
        entryTphfixe.delete(0, tk.END)
        entryTphport.delete(0, tk.END)
        entryMail.delete(0, tk.END)
        entryAdhesion.delete(0, tk.END)
        entryNaissance.delete(0, tk.END)
        entryProfession.delete(0, tk.END)
        entryLettre.delete(0, tk.END)
        entryCotisation.delete(0, tk.END)
        entryRelance.delete(0, tk.END)
     
        # Réinitialiser les placeholders
        setup_placeholder(entryNom, "Entrez votre nom ici")
        setup_placeholder(entryPrenom, "Entrez votre prénom ici")
     
     
    def modifier_donnees():
        """Fonction pour modifier un adhérent (à implémenter)"""
        messagebox.showinfo("Modifier", "Fonction MODIFIER à implémenter")
     
     
    def supprimer_donnees():
        """Fonction pour supprimer un adhérent"""
        reponse = messagebox.askyesno(
            "Confirmation", "Voulez-vous vraiment supprimer cet adhérent ?"
        )
        if reponse:
            effacer_formulaire()
            messagebox.showinfo("Suppression", "Adhérent supprimé")
     
     
    # Fonction helper pour créer des lignes avec label et entry
    def create_entry_row(parent, label_text, entry_width, row_num):
        """Crée une ligne avec label aligné à gauche et entry"""
        label = tk.Label(parent, text=label_text, anchor="w", bg="#f0f0f0")
        label.grid(row=row_num, column=0, sticky="w", padx=10, pady=5)
     
        entry = tk.Entry(parent, width=entry_width)
        entry.grid(row=row_num, column=1, sticky="w", padx=10, pady=5)
     
        return entry
     
     
    def create_tip_label(parent, text, row_num):
        """Crée un label de conseil en rouge"""
        tip = tk.Label(parent, text=text, fg="red", font=("Helvetica", 8), bg="#f0f0f0")
        tip.grid(row=row_num, column=2, sticky="w", padx=5, pady=5)
     
     
    # ----------------- Configuration de la fenêtre principale -----------------
    app = tk.Tk()
    app.title("Assistance Humanitaire Internationale")
    app.configure(bg="#e8f4f8")
     
    # Polices
    titre_font = font.Font(family="Helvetica", size=18, weight="bold")
    section_font = font.Font(family="Helvetica", size=11, weight="bold")
     
    # ----------------- En-tête avec titre -----------------
    frame_header = tk.Frame(app, bg="#4a90e2", height=80)
    frame_header.pack(fill="x", pady=(0, 15))
     
    labelTitre = tk.Label(
        frame_header,
        text="SAISIE ADHÉRENTS",
        fg="white",
        bg="#4a90e2",
        font=titre_font,
        pady=15
    )
    labelTitre.pack()
     
    # ----------------- Conteneur principal avec padding -----------------
    main_container = tk.Frame(app, bg="#e8f4f8")
    main_container.pack(fill="both", expand=True, padx=20, pady=10)
     
    # ----------------- Frame pour les deux colonnes -----------------
    content_frame = tk.Frame(main_container, bg="#e8f4f8")
    content_frame.pack(fill="both", expand=True)
     
    # ========== COLONNE GAUCHE : COORDONNÉES ==========
    frame_coordonnees = tk.LabelFrame(
        content_frame,
        text="📋 Coordonnées",
        font=section_font,
        bg="#f0f0f0",
        relief="groove",
        borderwidth=2,
        padx=15,
        pady=15
    )
    frame_coordonnees.grid(row=0, column=0, sticky="nsew", padx=(0, 10))
     
    # Nom et Prénom
    entryNom = create_entry_row(frame_coordonnees, "Nom :", 35, 0)
    setup_placeholder(entryNom, "Entrez votre nom ici")
    create_tip_label(frame_coordonnees, "Utiliser le - pour noms composés", 0)
     
    entryPrenom = create_entry_row(frame_coordonnees, "Prénom :", 35, 1)
    setup_placeholder(entryPrenom, "Entrez votre prénom ici")
    create_tip_label(frame_coordonnees, "Utiliser le - pour prénoms composés", 1)
     
    # Séparateur
    tk.Frame(frame_coordonnees, height=2, bg="#d0d0d0").grid(row=2, column=0, columnspan=3, sticky="ew", pady=10, padx=10)
     
    # Adresses
    entryAdresse1 = create_entry_row(frame_coordonnees, "Adresse 1 :", 45, 3)
    entryAdresse2 = create_entry_row(frame_coordonnees, "Adresse 2 :", 45, 4)
     
    # Code Postal et Ville sur la même ligne
    row_cp_ville = tk.Frame(frame_coordonnees, bg="#f0f0f0")
    row_cp_ville.grid(row=5, column=0, columnspan=3, sticky="w", pady=5)
     
    tk.Label(row_cp_ville, text="Code Postal :", anchor="w", bg="#f0f0f0").pack(side="left", padx=(10, 5))
    entryCpostal = tk.Entry(row_cp_ville, width=10)
    entryCpostal.pack(side="left", padx=5)
     
    tk.Label(row_cp_ville, text="Ville :", anchor="w", bg="#f0f0f0").pack(side="left", padx=(20, 5))
    entryVille = tk.Entry(row_cp_ville, width=30)
    entryVille.pack(side="left", padx=5)
     
    # Séparateur
    tk.Frame(frame_coordonnees, height=2, bg="#d0d0d0").grid(row=6, column=0, columnspan=3, sticky="ew", pady=10, padx=10)
     
    # Téléphones
    entryTphfixe = create_entry_row(frame_coordonnees, "Tél. fixe :", 20, 7)
    create_tip_label(frame_coordonnees, "Ex: 01 23 45 67 89 ou 0033 1 23 45 67 89", 7)
     
    entryTphport = create_entry_row(frame_coordonnees, "Tél. portable :", 20, 8)
    create_tip_label(frame_coordonnees, "Ex: 06 12 34 56 78 ou 0033 6 12 34 56 78", 8)
     
    # Mail
    entryMail = create_entry_row(frame_coordonnees, "Email :", 40, 9)
     
     
    # ========== COLONNE DROITE : INFORMATIONS ADHÉSION ==========
    frame_adhesion = tk.LabelFrame(
        content_frame,
        text="👤 Informations Adhésion",
        font=section_font,
        bg="#f0f0f0",
        relief="groove",
        borderwidth=2,
        padx=15,
        pady=15
    )
    frame_adhesion.grid(row=0, column=1, sticky="nsew", padx=(10, 0))
     
    # Champs adhésion
    entryAdhesion = create_entry_row(frame_adhesion, "Année Adhésion :", 10, 0)
     
    entryNaissance = create_entry_row(frame_adhesion, "Date de naissance :", 15, 1)
    create_tip_label(frame_adhesion, "Format: jj/mm/aaaa", 1)
     
    entryProfession = create_entry_row(frame_adhesion, "Profession :", 30, 2)
     
    # Séparateur
    tk.Frame(frame_adhesion, height=2, bg="#d0d0d0").grid(row=3, column=0, columnspan=3, sticky="ew", pady=10, padx=10)
     
    entryLettre = create_entry_row(frame_adhesion, "Lettre info :", 5, 4)
    create_tip_label(frame_adhesion, "Tapez O ou N", 4)
     
    entryCotisation = create_entry_row(frame_adhesion, "Année Cotisation :", 10, 5)
     
    entryRelance = create_entry_row(frame_adhesion, "Relance Cotisation :", 5, 6)
     
    # Configuration des poids pour expansion
    content_frame.columnconfigure(0, weight=1)
    content_frame.columnconfigure(1, weight=1)
     
    # ----------------- Frame des Boutons -----------------
    frame_boutons = tk.Frame(app, bg="#e8f4f8", pady=20)
    frame_boutons.pack(side="bottom", fill="x")
     
    # Style des boutons avec plus de padding
    button_style = {"font": ("Helvetica", 10, "bold"), "padx": 20, "pady": 8, "width": 12}
     
    Button0 = tk.Button(
        frame_boutons,
        text="✓ VALIDER",
        command=valider_donnees,
        bg="#90EE90",
        **button_style
    )
    Button0.pack(side="left", padx=15)
     
    Button1 = tk.Button(
        frame_boutons,
        text="✎ MODIFIER",
        command=modifier_donnees,
        bg="#87CEEB",
        **button_style
    )
    Button1.pack(side="left", padx=15)
     
    Button2 = tk.Button(
        frame_boutons,
        text="✗ SUPPRIMER",
        command=supprimer_donnees,
        bg="#FFB6C1",
        **button_style
    )
    Button2.pack(side="left", padx=15)
     
    Button3 = tk.Button(
        frame_boutons,
        text="⏻ QUITTER",
        command=app.quit,
        bg="#FFA07A",
        **button_style
    )
    Button3.pack(side="right", padx=15)
     
    app.mainloop()
    Nom : Copie d'écran_20251030_171726.png
Affichages : 149
Taille : 65,3 Ko
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

Discussions similaires

  1. Onclick avec l'objet Input Button ne fonctionne pas correctement
    Par jpwitz dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 28/01/2017, 17h18
  2. Ajouter un input (appendchild) ne fonctionne pas
    Par patricktoulon dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 15/11/2015, 09h29
  3. [PHP 5.5] input submit ne fonctionne pas
    Par chtony845 dans le forum Langage
    Réponses: 15
    Dernier message: 22/07/2015, 01h10
  4. Formulaire AJAX, élément input radio ne fonctionne pas
    Par benflodu69 dans le forum Langage
    Réponses: 4
    Dernier message: 26/05/2014, 00h02
  5. HTML5 input required ne fonctionne pas
    Par manbar dans le forum Balisage (X)HTML et validation W3C
    Réponses: 1
    Dernier message: 25/11/2013, 09h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo