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

Contribuez Python Discussion :

[FAQ Tkinter] Comment contrôler la saisie du texte dans un widget Entry ?


Sujet :

Contribuez Python

  1. #1
    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 [FAQ Tkinter] Comment contrôler la saisie du texte dans un widget Entry ?
    Bonjour,

    Comme je trouve que la partie de la FAQ sur le Widget Entry un peut légère je vous propose de rajouter du piment avec ce qui suit:

    ---
    Comment contrôler la saisie du texte dans un widget Entry ?

    Il existe deux manières de procéder: La validation ou la trace. La première interviens avant la modification du texte du Widget et la seconde solution permet d'en vérifier la saisie.

    La validation:

    Le Widget Entry dispose des options validate et validatecommand (ou vcmd, ce qui est exactement la même chose) permettant le contrôle de la saisie du texte.

    L'option validatecommand (vcmd) indique la fonction qui doit être utilisée pour valider le texte. Cette fonction doit impérativement retourner une valeur booléenne. True valideras la saisie et False la refuseras.
    La difficulté est ici que si la fonction ne retourne pas une valeur booléenne validate passe à None et la validation ne se fait plus, le seul moyen de réactiver celle ci étant de redonner sa valeur à l'option validate (widget.config(validate=valeur) par exemple).
    Il est possible de passer les paramètres suivants à la fonction:
    %d Type de l'action: 1 pour insert, 0 pour delete, ou -1 pour une validation "focus", "forced" ou "textvariable". Attention, c'est un string.
    %i Index du caractère à insérer/effacer, sinon -1.
    %P La valeur que l'entrée de texte doit modifier. Si vous configurez une nouvelle textvariable pour le widget , ce sera la valeur de cette textvariable.
    %s La valeur avant l'édition.
    %S La chaîne insérée/effacée, sinon {}
    %v Le type de validation actuel.
    %V Le type de validation qui a déclenché l'appel (key, focusin, focusout, forced).
    %W Le nom tcl/tk du widget.
    L'option validate détermine le type d’événement pour lequel on dois utiliser la fonction indiquée par validatecommand.
    Les événements possible sont:
    none jamais
    all tous
    key une touche
    focus le widget prend ou perd le focus
    focusin le widget prend le focus
    focusout le widget perd le focus
    L'exemple simple suivant montre un Widget Entry ne prenant en compte que la saisie de chiffres pour un événement de type 'key', soit l'appui sur une touche donc.
    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
    try:
        import Tkinter as Tk
    except:
        import tkinter as Tk
     
     
    def OnValidate(S):
        if S.isdigit():
            return True
        return False
     
    root = Tk.Tk()
    validatecmd = (root.register(OnValidate), '%S')
    e = Tk.Entry(root, validate="key", vcmd=validatecmd)
    e.pack()
    root.mainloop()
    Outre le fait que vous pouvez spécifier une action dans la fonction de validation si votre condition n'est pas remplie le Widget Entry propose une option invalidcommand (ou invcmd) permettant de spécifier une fonction qui seras évaluée si la fonction de vcmd retourne False. La fonction de invcmd accepte les mêmes paramètres que celle de vcmd.

    Un exemple avec le code précédent:
    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
    try:
        import Tkinter as Tk
    except:
        import tkinter as Tk
     
     
    def OnValidate(S):
        if S.isdigit():
            return True
        return False
     
    def OnError(S):
        t = Tk.Toplevel(root)
        Tk.Label(t, text="Error: Invalid input %s" % S).pack(padx=5, pady=5)
        Tk.Button(t, text="Ok", command=t.destroy).pack(padx=5, pady=5)
     
    root = Tk.Tk()
    validatecmd = (root.register(OnValidate), '%S')
    errorcmd = (root.register(OnError), '%S')
    e = Tk.Entry(root, validate="key", invcmd=errorcmd, vcmd=validatecmd)
    e.pack()
    root.mainloop()
    La trace:

    Pour tracer le contenu de l'Entry nous utilisons la classe Variable Tkinter, et plus précisément la classe StringVar puisque le contenu du Widget Entry est du texte.
    La classe Variable permet d’exécuter une fonction lorsque la valeur change (Merci de vous reporter à la documentation) et est utilisable avec l'option textvariable du Widget Entry.
    Un exemple simple de son utilisation:
    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
    try:
        import Tkinter as Tk
    except:
        import tkinter as Tk
     
     
    def OnValidate(*args):
        for c in s.get():
            if c.isdigit():
                continue
            t = Tk.Toplevel(root)
            Tk.Label(t, text="Only numbers please").pack(padx=5, pady=5)
            Tk.Button(t, text="Ok", command=t.destroy).pack(padx=5, pady=5)
     
    root = Tk.Tk()
    s = Tk.StringVar()
    s.trace_variable("w", OnValidate)
    e = Tk.Entry(root, textvariable=s)
    e.pack()
    root.mainloop()
    Ici nous n'affichons qu'un Widget Toplevel pour rester poli avec l'utilisateur mais rien n’empêche de désactiver momentanément la trace pour modifier la valeur de s.

    Attention: Il est maladroit de mélanger les deux solutions sous peine de voir les deux événements entrer en interaction.
    ---

    Votre avis ?
    Merci d'utiliser le forum pour les questions techniques.

  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
    Question sur la présentation:
    FAQ Python
    - vous devez proposer la question ainsi que la réponse avec le tag [FAQ]
    - placez la Q/R complète dans une balises [quote]


    Comme ceci ?

    Comment contrôler la saisie du texte dans un widget Entry ?

    Il existe deux manières de procéder: La validation ou la trace. La première interviens avant la modification du texte du Widget et la seconde solution permet d'en vérifier la saisie.

    La validation:

    Le Widget Entry dispose des options validate et validatecommand (ou vcmd, ce qui est exactement la même chose) permettant le contrôle de la saisie du texte.

    L'option validatecommand (vcmd) indique la fonction qui doit être utilisée pour valider le texte. Cette fonction doit impérativement retourner une valeur booléenne. True valideras la saisie et False la refuseras.
    La difficulté est ici que si la fonction ne retourne pas une valeur booléenne validate passe à None et la validation ne se fait plus, le seul moyen de réactiver celle ci étant de redonner sa valeur à l'option validate (widget.config(validate=valeur) par exemple).
    Il est possible de passer les paramètres suivants à la fonction:
    %d Type de l'action: 1 pour insert, 0 pour delete, ou -1 pour une validation "focus", "forced" ou "textvariable". Attention, c'est un string.
    %i Index du caractère à insérer/effacer, sinon -1.
    %P La valeur que l'entrée de texte doit modifier. Si vous configurez une nouvelle textvariable pour le widget , ce sera la valeur de cette textvariable.
    %s La valeur avant l'édition.
    %S La chaîne insérée/effacée, sinon {}
    %v Le type de validation actuel.
    %V Le type de validation qui a déclenché l'appel (key, focusin, focusout, forced).
    %W Le nom tcl/tk du widget.
    L'option validate détermine le type d’événement pour lequel on dois utiliser la fonction indiquée par validatecommand.
    Les événements possible sont:
    none jamais
    all tous
    key une touche
    focus le widget prend ou perd le focus
    focusin le widget prend le focus
    focusout le widget perd le focus
    L'exemple simple suivant montre un Widget Entry ne prenant en compte que la saisie de chiffres pour un événement de type 'key', soit l'appui sur une touche donc.
    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
    try:
        import Tkinter as Tk
    except:
        import tkinter as Tk
     
     
    def OnValidate(S):
        if S.isdigit():
            return True
        return False
     
    root = Tk.Tk()
    validatecmd = (root.register(OnValidate), '%S')
    e = Tk.Entry(root, validate="key", vcmd=validatecmd)
    e.pack()
    root.mainloop()
    Outre le fait que vous pouvez spécifier une action dans la fonction de validation si votre condition n'est pas remplie le Widget Entry propose une option invalidcommand (ou invcmd) permettant de spécifier une fonction qui seras évaluée si la fonction de vcmd retourne False. La fonction de invcmd accepte les mêmes paramètres que celle de vcmd.

    Un exemple avec le code précédent:
    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
    try:
        import Tkinter as Tk
    except:
        import tkinter as Tk
     
     
    def OnValidate(S):
        if S.isdigit():
            return True
        return False
     
    def OnError(S):
        t = Tk.Toplevel(root)
        Tk.Label(t, text="Error: Invalid input %s" % S).pack(padx=5, pady=5)
        Tk.Button(t, text="Ok", command=t.destroy).pack(padx=5, pady=5)
     
    root = Tk.Tk()
    validatecmd = (root.register(OnValidate), '%S')
    errorcmd = (root.register(OnError), '%S')
    e = Tk.Entry(root, validate="key", invcmd=errorcmd, vcmd=validatecmd)
    e.pack()
    root.mainloop()
    La trace:

    Pour tracer le contenu de l'Entry nous utilisons la classe Variable Tkinter, et plus précisément la classe StringVar puisque le contenu du Widget Entry est du texte.
    La classe Variable permet d’exécuter une fonction lorsque la valeur change (Merci de vous reporter à la documentation) et est utilisable avec l'option textvariable du Widget Entry.
    Un exemple simple de son utilisation:
    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
    try:
        import Tkinter as Tk
    except:
        import tkinter as Tk
     
     
    def OnValidate(*args):
        for c in s.get():
            if c.isdigit():
                continue
            t = Tk.Toplevel(root)
            Tk.Label(t, text="Only numbers please").pack(padx=5, pady=5)
            Tk.Button(t, text="Ok", command=t.destroy).pack(padx=5, pady=5)
     
    root = Tk.Tk()
    s = Tk.StringVar()
    s.trace_variable("w", OnValidate)
    e = Tk.Entry(root, textvariable=s)
    e.pack()
    root.mainloop()
    Ici nous n'affichons qu'un Widget Toplevel pour rester poli avec l'utilisateur mais rien n’empêche de désactiver momentanément la trace pour modifier la valeur de s.

    Attention: Il est maladroit de mélanger les deux solutions sous peine de voir les deux événements entrer en interaction.
    Merci d'utiliser le forum pour les questions techniques.

  3. #3
    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
    La classe Variable permet d’exécuter une fonction lorsque la valeur change
    Pas très heureux ceci

    Le sujet étant le Widget Entry je ne pense pas que la classe Variable soit a expliquer.
    Une idée pour ce passage ?
    Merci d'utiliser le forum pour les questions techniques.

  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
    La première interviens avant l’insertion dans le Widget
    Que pensez vous de ceci ?
    La première interviens avant la modification du texte du Widget
    ?
    Merci d'utiliser le forum pour les questions techniques.

  5. #5
    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
    Pas mal d'edit en fait : Je vais attendre vos réactions.
    Merci d'utiliser le forum pour les questions techniques.

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 240
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 240
    Points : 36 696
    Points
    36 696
    Par défaut
    Salut,

    J'ai deux remarques de "fond".

    Plutôt que de parler de "Comment contrôler la saisie du texte dans un widget Entry ?", il serait plus sage de se restreindre à "Comment utiliser la validation du widget Entry?".

    Car, l'usage des variables est "plus large" que... et, après tout, la grosse difficulté est dans la mise en œuvre de "validate".

    Je voulais ensuite parler de "forme" mais à la rédaction, je m'aperçois que ce qui est "brouillardeux" n'est pas tant validateCommand que la création de fonction appelables par Tcl (en général).

    Pour le coup, c'est quelque chose de vraiment spécifique à tkinter mais je n'ai pas trouvé de documentation satisfaisante ailleurs que dans les sources (et quelques exemples qui traînent ici ou là.)


    "idéalement", ce serait peut être pas mal d'avoir 2/3 pages sur cela avec des explications / recommandations. Une fois cela écrit, il sera certainement plus simple de raconter la validation du widget Entry.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    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
    Bonsoir wiztricks,

    Dans un premier temps merci de votre réponse.

    A vrais dire je viens de me faire mon 'bas à sable' avec trois propositions:
    Une modification de la FAQ
    Un ajout 'simple' à la FAQ
    Un Ajout 'piège pour moi' à la FAQ: Ce post. Piège ? Le sujet l'est en effet. La validation de l'Entry l'est.
    Piège aussi car je teste ma capacité a expliquer.

    Plutôt que de parler de "Comment contrôler la saisie du texte dans un widget Entry ?", il serait plus sage de se restreindre à "Comment utiliser la validation du widget Entry?".

    Car, l'usage des variables est "plus large" que... et, après tout, la grosse difficulté est dans la mise en œuvre de "validate".
    Comme dit plus haut "validate" est plein de pièges (que j'ai essayer d'éviter dans le texte) et mérite sans doute
    "idéalement", ce serait peut être pas mal d'avoir 2/3 pages sur cela avec des explications / recommandations.
    C'est pour cela que j'ai proposé la solution textvariable (qui est aussi une option du Widget, je reste donc sur celui-ci) pour avoir une 'solution plus simple'

    Car, l'usage des variables est "plus large" que...
    C'est ici pour l'option "textvariable"
    A noter ():
    et est utilisable avec l'option textvariable du Widget Entry.
    Je voulais ensuite parler de "forme" mais à la rédaction, je m'aperçois que ce qui est "brouillardeux" n'est pas tant validateCommand que la création de fonction appelables par Tcl (en général).
    register... Votre avis sur une proposition de code ?

    Je voulais ensuite parler de "forme"
    N'hésitez pas ! C'est mon but en fait.

    @+
    Merci d'utiliser le forum pour les questions techniques.

Discussions similaires

  1. Réponses: 3
    Dernier message: 25/01/2014, 08h50
  2. Comment limiter la saisie à deux décimales dans mon widget Text ?
    Par Nicolas Dansel dans le forum SWT/JFace
    Réponses: 3
    Dernier message: 09/09/2009, 17h13
  3. Réponses: 2
    Dernier message: 07/11/2008, 17h34
  4. [C# Datagrid] Comment contrôler la saisie d'un colonne ?
    Par kinou dans le forum Windows Forms
    Réponses: 4
    Dernier message: 18/05/2006, 11h15
  5. [Tkinter] ecrire un texte dans un widget entry
    Par thierry_b dans le forum Tkinter
    Réponses: 3
    Dernier message: 15/12/2005, 12h38

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