Précédent   Forum du club des développeurs et IT Pro > Autres langages > Python & Zope > Contribuez
Contribuez Proposez vos articles, cours, tutoriels, faq, sources pour Python & Zope
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 13/05/2012, 18h51   #1
PauseKawa
Expert Confirmé
 
Avatar de PauseKawa
 
Homme Patrice BLANGARIN
Technicien Help Desk, maintenance, réseau, système et +
Inscription : juin 2006
Messages : 2 650
Détails du profil
Informations personnelles :
Nom : Homme Patrice BLANGARIN
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 650
Points : 3 776
Points : 3 776
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:
Citation:
%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:
Citation:
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 :
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 :
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 :
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.
PauseKawa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/05/2012, 20h31   #2
PauseKawa
Expert Confirmé
 
Avatar de PauseKawa
 
Homme Patrice BLANGARIN
Technicien Help Desk, maintenance, réseau, système et +
Inscription : juin 2006
Messages : 2 650
Détails du profil
Informations personnelles :
Nom : Homme Patrice BLANGARIN
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 650
Points : 3 776
Points : 3 776
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 ?

Citation:
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:
Citation:
%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:
Citation:
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 :
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 :
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 :
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.
PauseKawa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/05/2012, 20h40   #3
PauseKawa
Expert Confirmé
 
Avatar de PauseKawa
 
Homme Patrice BLANGARIN
Technicien Help Desk, maintenance, réseau, système et +
Inscription : juin 2006
Messages : 2 650
Détails du profil
Informations personnelles :
Nom : Homme Patrice BLANGARIN
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 650
Points : 3 776
Points : 3 776
Citation:
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.
PauseKawa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/05/2012, 21h23   #4
PauseKawa
Expert Confirmé
 
Avatar de PauseKawa
 
Homme Patrice BLANGARIN
Technicien Help Desk, maintenance, réseau, système et +
Inscription : juin 2006
Messages : 2 650
Détails du profil
Informations personnelles :
Nom : Homme Patrice BLANGARIN
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 650
Points : 3 776
Points : 3 776
Citation:
La première interviens avant l’insertion dans le Widget
Que pensez vous de ceci ?
Citation:
La première interviens avant la modification du texte du Widget
?
__________________
Merci d'utiliser le forum pour les questions techniques.
PauseKawa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/05/2012, 21h39   #5
PauseKawa
Expert Confirmé
 
Avatar de PauseKawa
 
Homme Patrice BLANGARIN
Technicien Help Desk, maintenance, réseau, système et +
Inscription : juin 2006
Messages : 2 650
Détails du profil
Informations personnelles :
Nom : Homme Patrice BLANGARIN
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 650
Points : 3 776
Points : 3 776
Pas mal d'edit en fait : Je vais attendre vos réactions.
__________________
Merci d'utiliser le forum pour les questions techniques.
PauseKawa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/05/2012, 21h08   #6
wiztricks
Expert Confirmé Sénior
 
Inscription : juin 2008
Messages : 3 739
Détails du profil
Informations forums :
Inscription : juin 2008
Messages : 3 739
Points : 4 581
Points : 4 581
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
wiztricks est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/05/2012, 21h59   #7
PauseKawa
Expert Confirmé
 
Avatar de PauseKawa
 
Homme Patrice BLANGARIN
Technicien Help Desk, maintenance, réseau, système et +
Inscription : juin 2006
Messages : 2 650
Détails du profil
Informations personnelles :
Nom : Homme Patrice BLANGARIN
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 650
Points : 3 776
Points : 3 776
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.

Citation:
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
Citation:
"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'

Citation:
Car, l'usage des variables est "plus large" que...
C'est ici pour l'option "textvariable"
A noter ():
Citation:
et est utilisable avec l'option textvariable du Widget Entry.
Citation:
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 ?

Citation:
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.
PauseKawa est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 00h12.


 
 
 
 
Partenaires

Hébergement Web