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

Tkinter Python Discussion :

Votre avis sur ce code - Générateur de mot de passe


Sujet :

Tkinter Python

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 65
    Points : 65
    Points
    65
    Par défaut Votre avis sur ce code - Générateur de mot de passe
    Bonjour, j'ai commencé un projet personnel qui consiste à créer un générateur de mot de passe que je ferai évoluer petit à petit vers un gestionnaire de mot de passe. (NB.Oui, je sais, il y en a pleins de gratuits )

    Mais avant de poursuivre plus en avant, j'aurai aimé avoir votre avis sur ce que j'ai déjà fait, voici le code (Python 3):

    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
    # /usr/bin/env python
    # -*- coding:Utf-8 -*-
     
    # Importation des modules
    from tkinter import *
    from tkinter import messagebox
    from tkinter import ttk
    import random
     
     
    # Définition des variables
    global password
    global liste
    global selection
    selection = ["ABCDEFGHJKMNPQRSTUVWXYZ", "abcdefghjkmnpqrstuvwxyz", \
                 "23456789", "#*/-+:\_&%!?"]
    liste = ["ABCDEFGHJKMNPQRSTUVWXYZ", "abcdefghjkmnpqrstuvwxyz", "23456789"]
    random.shuffle(liste)
     
     
    def combine(x):
        option = ((var_maj, 0), (var_min, 1), (var_num, 2), (var_spe, 3))
        if option[x][0].get() == True:
            liste.append(selection[option[x][1]])
        else:
            liste.remove(selection[option[x][1]])
     
     
    def generate(event):
        "Génération du mot de passe"
        if liste == []:
            messagebox.showinfo(message="Veuillez choisir au moins une option")
        else:
            try:
                nb = nbcar.get()
                if nb < 4 or nb > 30:
                    messagebox.showinfo(message="minumum 4 caractères, maximum 30 caractères")
                else:
                    compteur = 0
                    position = -1
                    D = []
                    while compteur < nb:
                        if position < len(liste) - 1:
                            position += 1
                        else:
                            position = 0
                        D = D + random.sample(liste[position], 1)
                        compteur += 1
                    random.shuffle(D)
                    D = "".join(D)
                    password.set(D)
            except:
                messagebox.showinfo(message="Veuillez indiquer un nombre de caractère pour le mot de passe")
     
     
    def addtoclip():
        text = password.get()
        if text == "":
            messagebox.showinfo(message="Merci de générer un mot de passe en appuyant sur -Entrée-")
        else:
            fenetre.clipboard_clear()
            fenetre.clipboard_append(text)
     
     
    def windowcenter(w, h):
        "Placer la fenêtre principal au centre"
        px = (fenetre.winfo_screenwidth() / 2) - (w / 2)
        py = (fenetre.winfo_screenheight() / 2) - (h / 2)
        fenetre.geometry("%dx%d+%d+%d" % (w, h, px, py))
     
    # Création de l'interface graphique
    fenetre = Tk()
    fenetre.title("Gpwd")
    fenetre.resizable(width=False, height=False)
     
    # Création des widgets checkbutton
    var_maj = BooleanVar()
    var_min = BooleanVar()
    var_num = BooleanVar()
    var_spe = BooleanVar()
     
    var_maj.set(True)
    var_min.set(True)
    var_num.set(True)
    var_spe.set(False)
     
    chk_maj = ttk.Checkbutton(fenetre, text="Majuscules",
                              variable=var_maj, command=lambda: combine(0),
                              onvalue=True, offvalue=False)
    chk_min = ttk.Checkbutton(fenetre, text="Minuscules",
                              variable=var_min, command=lambda: combine(1),
                              onvalue=True, offvalue=False)
    chk_num = ttk.Checkbutton(fenetre, text="Chiffres",
                              variable=var_num, command=lambda: combine(2),
                              onvalue=True, offvalue=False)
    chk_spe = ttk.Checkbutton(fenetre, text="Spéciaux",
                              variable=var_spe, command=lambda: combine(3),
                              onvalue=True, offvalue=False)
     
    # Création des widgets label
    label_nbcar = ttk.Label(text="Nbre de caractère pour le mot de passe")
    label_pwd = ttk.Label(text="Mot de passe")
     
    # Création des widgets entry
    nbcar = IntVar()
    nbcar.set(7)
    entree_nbcar = ttk.Entry(textvariable=nbcar)
    password = StringVar()
    entree_pwd = ttk.Entry(textvariable=password)
     
    # Création du widget button
    bouton = ttk.Button(text="Copier dans le presse-papier", command=addtoclip)
     
    # Placement des widgets
    # Checkbutton
    chk_maj.grid(column=1, row=1, sticky=W, padx=3, pady=3)
    chk_min.grid(column=1, row=2, sticky=W, padx=3, pady=3)
    chk_num.grid(column=2, row=1, sticky=W, padx=3, pady=3)
    chk_spe.grid(column=2, row=2, sticky=W, padx=3, pady=3)
     
    # Label et Entry pour nombre de caractères
    label_nbcar.grid(column=1, row=3, columnspan=2, sticky='W', padx=3, pady=1)
    entree_nbcar.grid(column=1, row=4, columnspan=2, sticky='WE', padx=3, pady=3)
     
    # Label et Entry pour mot de passe
    label_pwd.grid(column=1, row=5, columnspan=2, sticky='W', padx=3, pady=1)
    entree_pwd.grid(column=1, row=6, columnspan=2, sticky='WE', padx=3, pady=3)
     
    # Button pour copie du mot de passe dans le presse-papier
    bouton.grid(column=1, row=7, columnspan=2, sticky='WE', padx=3, pady=3)
     
    fenetre.bind('<Return>', generate)
    fenetre.update_idletasks()
    w = fenetre.winfo_reqwidth()
    h = fenetre.winfo_reqheight()
    windowcenter(w, h)
     
    fenetre.mainloop()
    J'aimerai bien que l'on me dise comment améliorer tout cela. Je ne maîtrise pas encore les concepts de classes mais je suis en train de m'y pencher.
    Pour la suite, j'aimerai afficher avant l'ouverture de la fenêtre principale une autre fenêtre où j'invite l'utilisateur à saisir son identifiant/mot de passe.

    D'aprés vous,comment devrais-je procédé? J'avais pensé utilisé la fonction Toplevel mais j'aimerai que cette fenêtre apparaisse avant tout le reste.
    Si je crée une classe, puis-je dans __init__ crée cette première fenêtre et si le couple mot de passe/identifiant est reconnu, je lance la fonction pour créer la fenêtre principale et fermer la première fenêtre?

    J'ai déjà fait un premier essai en encapsulant tout dans une classe mais sans succès. Impossible de fermer la première fenêtre à l'aide de mafenetre.quit(), de plus, les checkbuttons ne sont plus correctement configurés (ils sont dans un état intermédiaire).

    Voilà, si des personnes pouvaient me guider un peu, ça serait vraiment sympa.

    Merci d'avance.

  2. #2
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Quelques notes

    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
    # /usr/bin/env python
    # -*- coding:Utf-8 -*-
     
    # Importation des modules
    # Sans importance ici mais évitez from tkinter import *
    from tkinter import *
    from tkinter import messagebox
    # Je ne vois pas l'interet de ttk
    import random
     
     
    # Définition des variables
    selection = ("ABCDEFGHJKMNPQRSTUVWXYZ", "abcdefghjkmnpqrstuvwxyz", \
                 "23456789", "#*/-+:\_&%!?")
    liste = ["ABCDEFGHJKMNPQRSTUVWXYZ", "abcdefghjkmnpqrstuvwxyz", "23456789"]
    random.shuffle(liste)
    # global inutile
     
    # Pour la logique de combine/generate je vous laisse seul maitre.
    def combine(x):
        option = ((var_maj, 0), (var_min, 1), (var_num, 2), (var_spe, 3))
        if option[x][0].get() == True:
            liste.append(selection[option[x][1]])
        else:
            liste.remove(selection[option[x][1]])
     
     
    def generate():
        "Génération du mot de passe"
        if liste:
            # Voir le return
            nb = nbcar_callback()
            if nb:  # != None
                if nb < 4 or nb > 30:
                    messagebox.showinfo(title="Gpwd",
                                        message="minumum 4 caractères, \
                                                 maximum 30 caractères")
                else:
                    compteur = 0
                    position = -1
                    D = []
                    while compteur < nb:
                        if position < len(liste) - 1:
                            position += 1
                        else:
                            position = 0
                        D += random.sample(liste[position], 1)
                        compteur += 1
                    random.shuffle(D)
                    D = "".join(D)
                    password.set(D)
            else:
                # nb == None
                messagebox.showinfo(title="Gpwd",
                                    message="Veuillez indiquer un nombre de \
                                             caractère pour le mot de passe")
        else:
            messagebox.showinfo(title="Gpwd",
                                message="Veuillez choisir au moins une option")
     
     
    def addtoclip():
        text = password.get()
        if text:
            fenetre.clipboard_clear()
            fenetre.clipboard_append(text)
        else:
            messagebox.showinfo(title="Gpwd", message="Merci de générer un mot \
                                de passe en appuyant sur -Entrée-")
     
     
    def nbcar_callback(*args):
        # On controle la saisie utilisateur.
        # Il est possible de passer par la validation de l'Entry (voir validate)
        # mais c'est largement suffisant ici.
        nb = nbcar.get()
        if nb:  # != ''
            # On tente de convertir en int
            try:
                nb = int(nb)
                return nb  # Pour generate()
            except ValueError:
                nbcar.set("7")
                messagebox.showinfo(title="Gpwd", message="Valeur invalide")
     
     
    def windowcenter(widget):
        "Placer la fenêtre au centre"
        widget.update()
        w = widget.winfo_reqwidth()
        h = widget.winfo_reqheight()
        px = (widget.winfo_screenwidth() / 2) - (w / 2)
        py = (widget.winfo_screenheight() / 2) - (h / 2)
        widget.geometry("%dx%d+%d+%d" % (w, h, px, py))
        widget.resizable(width=False, height=False)
     
     
    def showlogin():
        passwords = [('root', 'pass'), ('admin', 'root'), ('austin57', 'austin57')]
        def verifpass():
            if (utilisateur.get(), mdp.get()) in passwords:
                toplogin.destroy()
                fenetre.deiconify()
            else:
                toplogin.destroy()
                fenetre.destroy()
     
        toplogin = Toplevel(fenetre)
        Label(toplogin, text="Utilisateur:").grid(row=0, column=0)
        utilisateur = Entry(toplogin, show='*', justify=CENTER)
        utilisateur.grid(row=0, column=1)
        Label(toplogin, text="Mot de passe:").grid(row=1, column=0)
        mdp = Entry(toplogin, show="*", justify=CENTER)
        mdp.grid(row=1, column=1)
        windowcenter(toplogin)
        utilisateur.bind('<Return>', lambda e: mdp.focus_set())
        utilisateur.bind("<KP_Enter>", lambda e: mdp.focus_set())
        mdp.bind('<Return>', lambda e: verifpass())
        mdp.bind("<KP_Enter>", lambda e: verifpass())
        utilisateur.focus_set()
     
     
    # Création de l'interface graphique
    fenetre = Tk()
    # On cache la fenetre le temps de la creer
    fenetre.withdraw()
    fenetre.title("Gpwd")
     
    # Création des widgets checkbutton
    var_maj = BooleanVar(value=True)
    var_min = BooleanVar(value=True)
    var_num = BooleanVar(value=True)
    var_spe = BooleanVar(value=False)
    # Un Widget Entry contient du texte. Utiliser IntVar c'est s'exposer à un ValueError
    # de la classe Variable elle même.
    nbcar = StringVar(value="7")
    nbcar.trace("w", nbcar_callback)
    password = StringVar()
     
    Checkbutton(fenetre, text="Majuscules", variable=var_maj,
                command=lambda: combine(0), onvalue=True,
                offvalue=False).grid(column=1, row=1, sticky=W, padx=3, pady=3)
    Checkbutton(fenetre, text="Minuscules", variable=var_min,
                command=lambda: combine(1), onvalue=True,
                offvalue=False).grid(column=1, row=2, sticky=W, padx=3, pady=3)
    Checkbutton(fenetre, text="Chiffres", variable=var_num,
                command=lambda: combine(2), onvalue=True,
                offvalue=False).grid(column=2, row=1, sticky=W, padx=3, pady=3)
    Checkbutton(fenetre, text="Spéciaux", variable=var_spe,
                command=lambda: combine(3), onvalue=True,
                offvalue=False).grid(column=2, row=2, sticky=W, padx=3, pady=3)
    Label(text="Nbre de caractère pour le mot de passe").grid(column=1, row=3,
                                                              columnspan=2,
                                                              sticky='W',
                                                              padx=3, pady=1)
    Label(text="Mot de passe").grid(column=1, row=5, columnspan=2, sticky='W',
                                    padx=3, pady=1)
    # Pour le focus
    label_nbcar = Entry(textvariable=nbcar)
    label_nbcar.grid(column=1, row=4, columnspan=2, sticky='WE', padx=3, pady=3)
    Entry(textvariable=password).grid(column=1, row=6, columnspan=2, sticky='WE',
                                      padx=3, pady=3)
    Button(text="Copier dans le presse-papier",
           command=addtoclip).grid(column=1, row=7, columnspan=2, sticky='WE',
                                   padx=3, pady=3)
     
    fenetre.bind('<Return>', lambda e: generate())
    # Pavé numérique
    fenetre.bind("<KP_Enter>", lambda e: generate())
    windowcenter(fenetre)
    label_nbcar.focus_set()
    label_nbcar.icursor(1)  # On se positionne après le "7"
    showlogin()
    fenetre.mainloop()
    Pour ce qui est des classes je ne vois rien dans le code qui le justifie.
    Si vous voulez vraiment utiliser les classes en voici un exemple
    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
    import tkinter as tk
     
     
    class Foo(tk.Tk):
        def __init__(self):
            tk.Tk.__init__(self)
            # Je vous laisse remplir
            self.withdraw()
            self.windowcenter(self)
            self.showlogin()
     
     
        def windowcenter(self, widget):
            "Placer la fenêtre au centre"
            widget.update()
            w = widget.winfo_reqwidth()
            h = widget.winfo_reqheight()
            px = (widget.winfo_screenwidth() / 2) - (w / 2)
            py = (widget.winfo_screenheight() / 2) - (h / 2)
            widget.geometry("%dx%d+%d+%d" % (w, h, px, py))
            widget.resizable(width=False, height=False)
     
     
        def showlogin(self):
            passwords = [('root', 'pass'), ('admin', 'root'), ('austin57', 'austin57')]
            def verifpass():
                if (utilisateur.get(), mdp.get()) in passwords:
                    toplogin.destroy()
                    self.deiconify()
                else:
                    toplogin.destroy()
                    self.destroy()
     
            toplogin = tk.Toplevel(self)
            tk.Label(toplogin, text="Utilisateur:").grid(row=0, column=0)
            utilisateur = tk.Entry(toplogin, show='*', justify=tk.CENTER)
            utilisateur.grid(row=0, column=1)
            tk.Label(toplogin, text="Mot de passe:").grid(row=1, column=0)
            mdp = tk.Entry(toplogin, show="*", justify=tk.CENTER)
            mdp.grid(row=1, column=1)
            self.windowcenter(toplogin)
            utilisateur.bind('<Return>', lambda e: mdp.focus_set())
            utilisateur.bind("<KP_Enter>", lambda e: mdp.focus_set())
            mdp.bind('<Return>', lambda e: verifpass())
            mdp.bind("<KP_Enter>", lambda e: verifpass())
            utilisateur.focus_set()
     
     
    if __name__ =='__main__':
        app = Foo()
        app.mainloop()
    @+

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 65
    Points : 65
    Points
    65
    Par défaut
    Merci PauseKawa pour cette réponse bien au-delà de ce que j'espérai.
    C'est vraiment pleins de petits trucs en plus par rapport à mon code original auquel je n'avais pas pensé alors que j'ai déjà vu les concepts (focus, cursor, *args...)

    Pour ttk, c'est uniquement pour l'esthétique que j'utilise ces widgets, mais je trouve qu'ils sont un poil plus compliqué à utiliser que les widgets standards.

    Juste encore une question, vous dites qu'il n'est pas nécessaire d'encapsuler l'application dans une classe, mais j'aimerai savoir à qu'elle moment il devient impératif d'utiliser l'encapsulation?
    J'ai compris le principe d'héritage et de polymorphisme et du coup je vois bien l'utilité de l'encapsulation lorsqu'on a recours à ces concepts mais j'ai du mal à comprendre l'utilisation de l'encapsulation seule?

    Encore un grand merci pour votre aide.

  4. #4
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Juste une petite différence, hors considérations POO.
    Maintenant vous avez besoin de votre code pour un autre, vous allez donc importer celui ci.
    Dans le cadre du premier code le Toplevel serait lancé dès l'import, normal puisque Python vas interpréter ce qu'il importe.
    Dans le cadre d'une classe vous devrez vous même créer l'instance.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    import lenomdetonpy
    f = lenomdetonpy.Foo()
    Après cela les classes sont bien utiles. Imaginez que vous deviez faire un classeur style excel. Vous allez définir chaque cellules (par exemple) avec des méthodes et attributs (type de données texte, date, calcul etc...). Vous n'allez pas faire x Entry pour chaque cellule sans doute.
    C'est le principe de la classe: Déclarer des attributs et méthodes pour construire des instances.

    Au passage regardez le code de la Classe InfoBulle.

    @+

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 65
    Points : 65
    Points
    65
    Par défaut
    Il ne me reste plus qu'à me replonger dans mon programme.

    Au passage, génial le coup des infos-bulles, je garde ça sous le coude. Une fois analysé et compris, je pense que je l'intégrerai à mon programme.

    A bientôt et merci pour le temps que vous passez à répondre aux questions de chacun car j'ai vu que vous êtes vraiment très actif sur le forum.

    Cordialement,

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [2.x] Votre avis sur le code généré par le générateur de CRUD
    Par DanaKil dans le forum Symfony
    Réponses: 1
    Dernier message: 26/05/2012, 04h10
  2. [XL-2003] Votre avis sur mon code en VBA ?
    Par [ZiP] dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 02/03/2010, 13h56
  3. MAX_CONNECTIONS: votre avis sur ce code
    Par Zartan dans le forum Administration
    Réponses: 2
    Dernier message: 31/01/2010, 04h34
  4. [FFT] Votre avis sur mon code
    Par deubelte dans le forum C++
    Réponses: 1
    Dernier message: 10/02/2007, 20h14
  5. [Code Prof]votre avis sur un code?
    Par granquet dans le forum Réseau
    Réponses: 6
    Dernier message: 11/04/2006, 20h41

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