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 :

validatecommand sur entry [Python 3.X]


Sujet :

Tkinter Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    514
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 514
    Par défaut validatecommand sur entry
    Bonjours, j'aimerait que mes entry ne prennent en compte que certains caractères, j'ai trouvé ça sur stackOverflow (vite fait édité par moi-même, pour comprendre je décortique petit à petit)
    mais là ... je n'y comprend rien...
    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
     
     
    from tkinter import *
     
    class window2:
    	def __init__(self):
     
     
    		self.text1 = Entry(root, validate = 'key', validatecommand = (root.register(self.validate),'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W'))
    		self.text1.grid()
     
    	def validate(self, action, index, value_if_allowed, prior_value, text, validation_type, trigger_type, widget_name):
    		if text in '0123456789.-+':
    			try:
    				float(value_if_allowed)
    				return True
    			except ValueError:
    				return False
    		else:
    			return False
     
    root = Tk()
    a = window2()
    root.mainloop()
    Je n'ai trouvé aucune doc, root.register(self.validate) et self, action, index, value_if_allowed, prior_value, text, validation_type, trigger_type, widget_name doit être la clé de la compréhension.
    Si je comprend bien la fonction renvoie True ou False donc root.register(True) ou root.register(False) c'est ça ?

    edit : si je comprend bien les quelques docs validatecommand = (root.register(self.validate) revient juste à validatecommand = True ou validatecommand = False c'est bien ça ?

  2. #2
    Membre très actif

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Billets dans le blog
    1
    Par défaut
    Non register enregistre une commande dans tcl pour servir de callback, c'est en fait je crois par là que passe tous les callbacks qu'on utilise dans tkinter d'ailleurs, event, options command et autres.

    Ce callback que tu lui fourniras devra juste retourner des booléens en fonction de ce que tu autorises dans ton entry ou pas, et il peut recevoir plusieurs arguments en fonction de qu'on spécifie comme arguments dans validatecommand.

  3. #3
    Membre très actif

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Billets dans le blog
    1
    Par défaut
    Un exemple étant plus parlant, comme quoi ça sert de garder plein de scripts divers qu'on fait dans un coin

    Voilà ce que ça pourrait donner avec un test sur les numéros de mois.

    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
    import tkinter as tk
     
    def verificationMois(valeur) :
        if not valeur :
            return True
        elif valeur.isdigit() and 1 <= int(valeur) <= 12 :
            return True
        return False
     
    def changerEtatBoutonValidation(*args) :
        boutonValider['state'] = tk.ACTIVE if varMois.get() else tk.DISABLED
     
    def enregistrerSaisies() :
        pass
     
    root = tk.Tk()
     
    varMois = tk.StringVar()
    varMois.trace('w', changerEtatBoutonValidation)
    champMois = tk.Entry(root, textvariable=varMois, width=10, font=('', 30))
    champMois.grid()
    _cmd = champMois.register(verificationMois)
    # %P défini ce que l'Entry contiendra si on autorise ou non cette nouvelle valeur
    champMois.configure(validatecommand=(_cmd, '%P'), validate='key')
    champMois.focus_set()
     
    boutonValider = tk.Button(root, text='valider', command=enregistrerSaisies, state=tk.DISABLED)
    boutonValider.grid()
     
    root.mainloop()
    Là, il y a un combiné de var.trace qui s'occupe d'activer le bouton valider, et du callback passer dans l'entry qui permet ou non la saisie en fonction de ce qu'on autorise.

    Il y a d'autres options que le %P, voir la doc de tkinter.

  4. #4
    Membre chevronné
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    514
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 514
    Par défaut
    J'ai produit ces quelques lignes de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    def FonctionTest(ajout):
    	if ajout in '123':
    		return True
    	else:
    		return False
     
     
    root = Tk()
    saisi = StringVar()
    entry = Entry(root, textvariable=saisi, validate='key', validatecommand=(root.register(FonctionTest), '%S' ))
    entry.grid()
     
    root.mainloop()
    qui m'on bien permis de comprendre le fonctionnement de validatecommand, si j'ai bien compris (register(fonction), a, b, c) quand il y a un événement 'key' alors validatecommand=fonction(a, b, c) ?
    par contre je ne comprend pas pourquoi quand ma FonctionTest est déclaré après j'ai NameError: name 'FonctionTest' is not defined alors que dans une classe ça marche

  5. #5
    Membre très actif

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par flapili Voir le message
    Jpar contre je ne comprend pas pourquoi quand ma FonctionTest est déclaré après j'ai NameError: name 'FonctionTest' is not defined alors que dans une classe ça marche
    Bah c'est normal, tu demandes l'enregistrement d'une fonction qui n'est pas encore définie, c'est comme si tu faisais var = maFontion que tu déclares plus bas.

    Alors que dans une classe toutes les méthodes, attributs sont déclarés à l'instance.

  6. #6
    Membre chevronné
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    514
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 514
    Par défaut
    je pensait justement que register() créait un callback et de ce faite la vérification de si la fonction existe ou non est fait lors de l'event , "mea culpa" comme dirait l'autre ^^

  7. #7
    Membre chevronné
    Homme Profil pro
    BTS SN IR
    Inscrit en
    Mai 2017
    Messages
    514
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : BTS SN IR

    Informations forums :
    Inscription : Mai 2017
    Messages : 514
    Par défaut
    Bonjours, je ne comprend pas comment récupérer le nom du widget dans la fonction quand je modifie l'entry
    un exemple est plus parlant alors voici :
    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
     
    from tkinter import *
     
    def FonctionTest(widget):
     
    	print(widget)
    	return True
     
    root = Tk()
    saisi = StringVar()
    ligneDeSaisi = Entry(root, textvariable=saisi)
    ligneDeSaisi.config(validate='key', validatecommand=(root.register(FonctionTest), '%W'))
    ligneDeSaisi.grid()
     
    root.mainloop()
    j'ai .!entry , y'a t'il un moyen d'avoir ligneDeSaisi ?


    edit : autant pour moi, même sur je fait print(ligneDeSaisi) il m'affiche ça, le problème c'est que je me retrouve avec un str et non on objet, si j'utilise un dictionnaire je suis obliger d'avoir comme clé .!entry c'est ça ? .... (si plusieurs entry j'ai .!entry2 , ect )
    et si je met mon entry dans un frame j'ai .!frame.!entry peut importe le nom du frame ou de l'entry ... en faite dans ma fonctionTest j'aimerai bien pouvoir faire widget.config(background='red')dans certaine situation...

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

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