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 :

Vérifier (et modifier) un entry lettre par lettre à la saisie (thread ?)


Sujet :

Tkinter 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 Vérifier (et modifier) un entry lettre par lettre à la saisie (thread ?)
    Bonsoir,

    Je cherche à vérifier (et modifier) un entry à chaque lettre tapée.

    J'ai commencé à voir cela avec un thread mais il me semble qu'il y a plus simple.

    Un exemple 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
    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
     
    from Tkinter import *
    from threading import Thread
    from os import linesep
     
    ListeAccents = {u'é':'e',u'è':'e',u'ê':'e',u'ë':'e',u'æ':'ae',u'ã':'a',u'ä':'a',u'á':'a',u'à':'a',u'â':'a',u'ä':'a',u'ù':'u',u'ô':'o',u'ö':'o',u'ç':'c',u'ï':'i',u'û':'u',u'î':'i',u'ñ':'n',u'À':'A',u'Á':'A',u'Â':'A',u'Ã':'A',u'Ä':'A',u'Å':'A',u'Æ':'AE',u'Ç':'C',u'È':'E',u'É':'E',u'Ê':'E',u'Ë':'E',u'Ñ':'N',u'Ì':'I',u'Í':'I',u'Î':'I',u'Ï':'I',u'Ï':'I',u'Ò':'O',u'Ó':'O',u'Ô':'O',u'Õ':'O',u'Ö':'O',u'Ü':'U',u'Û':'U',u'Ú':'U',u'Ù':'U',u'Œ':'OE',u'œ':'oe'}
     
    class MonAppli_Globals():
        EntryChoixRep_StringVar = None
        Terminated = False
     
    class Normalise_MonPB(Thread):
        def __init__(self):
            Thread.__init__(self)
            MonAppli_Globals.Terminated = False
     
        def run(self):
            while not MonAppli_Globals.Terminated:
                Entree = MonAppli_Globals.EntryChoixRep_StringVar.get()
                if Entree:
                    if ListeAccents.has_key(Entree[-1]):
                        print 'pass'
                        RetourNom = Entree.replace(Entree[-1],ListeAccents[Entree[-1]])
                        MonAppli_Globals.EntryChoixRep_StringVar.set(RetourNom)
                    if Entree[-1] ==' ':
                        RetourNom = Entree.replace(' ','_') # Non mis dans ListeAccents car juste utile ici 
                        MonAppli_Globals.EntryChoixRep_StringVar.set(RetourNom)
     
    class mon_app(Tk):
        def C_Ok(self):
            MonAppli_Globals.Terminated = True
            print "Ok"
            self.quit()
     
        def C_Quit(self):
            MonAppli_Globals.Terminated = True
            self.destroy()
     
        def __init__(self,parent):
            Tk.__init__(self,parent)
            self.parent = parent
            self.initialize()
     
        def initialize(self, event = None):
            self.geometry("%dx%d+%d+%d" % (230,130, (self.winfo_screenwidth()-230)/2, (self.winfo_screenheight()-130)/2 ) )
            self.resizable(False,False)
            Label(self, fg="dark slate blue", text= linesep + "Texte à vérifier :").pack(side=TOP)
            MonAppli_Globals.EntryChoixRep_StringVar = StringVar()
            EntryChoixRep = Entry(self, bg="white", fg="dark slate blue", justify = "center", textvariable= MonAppli_Globals.EntryChoixRep_StringVar)
            EntryChoixRep.pack(side=TOP, pady=10)
            MonAppli_Globals.EntryChoixRep_StringVar.set("")
            Frame(self, height=2, bd=1, relief=SUNKEN).pack(side=TOP, fill=X, padx=5, pady=5)
            Button(self, text="Valider", fg='dark slate blue', activebackground='white', activeforeground='#2a7aff', command = self.C_Ok).pack(side=LEFT, padx=10)
            Button(self, text="Annuler", fg='dark slate blue', activebackground='white', activeforeground='#2a7aff', command = self.C_Quit).pack(side=RIGHT, padx=10)
            EntryChoixRep.focus_set()
            self.bind('<Escape>', self.quit )
            Normalise_MonPB().start()
     
    if __name__ == "__main__":
        app = mon_app(None)
        app.mainloop()
    Existe t'il une solution plus simple ?

    Merci

    Edit : Cest un copier coller du code original et je n'avais pas vus le pb sur la sortie de thread Dans l'original cela tourne bien sur
    La question reste la même : existe t'il une autre solution.

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 478
    Points : 9 280
    Points
    9 280
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    On peut déclarer le déclenchement d'évènements par des touches clavier et son traitement par une fonction adaptée. Tu peux t'inspirer de mon tuto ici (il s'agissait de limiter l'écriture à certaines touches):

    http://python.jpvweb.com/mesrecettes...alid_car_entry

    Voir la notice de tkinter: http://infohost.nmt.edu/tcc/help/pubs/tkinter.pdf. Il y a toutes les infos sur le déclenchement des évènements possibles (chap. 30).

    Tyrtamos

  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
    Bonjour tyrtamos et merci de ta réponse.

    J'avais effectivement essayer pendant un moment de jouer sur les events et bind (résultats pas terribles : décalage affichage/traitement etc...) avant de passer au thread. Mais avec la notion de validation c'est autre chose.
    J'avais bien vus cela sur effbot.org/tkinterbook (puisque tu y fais référence) mais comme d'habitude je suis passer à coter.

    Dans ton code bloquer les touches non voulues marche à merveille.
    Je parle dans le cadre de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
        def veriftouche(self):
            if (self.touche.char in "0123456789") or (self.touche.keysym == "BackSpace"):
                return True
            else:
                return False
    Par contre pour que j'arrive à faire l'inverse c'est autre chose...
    Le but pour moi c'est de remplacer dynamiquement les caractères accentués et de laisser les autres tels quels.
    Donc si je me contente de suivre ton exemple par un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        def veriftouche(self):
            if (self.touche.char not in ListeAccents.keys()) or (self.touche.keysym == "BackSpace"):
                return True
            else:
                return False
    Pas de problème, c'est le même code et cela tourne.

    Par contre si je commence à modifier self.touche.char la validation ne se fais plus.

    Un exemple (toujours sur ton 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
    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import Tkinter
     
    class Application(Tkinter.Frame):
     
        def __init__(self, master=None):
            Tkinter.Frame.__init__(self, master, background="ivory")
     
            self.grid()
            self.saisie=Tkinter.Entry(self, background="white", width=50)
            self.saisie.configure(validate='key',validatecommand=self.veriftouche)
            self.saisie.bind("<Key>", self.quelletouche)
            self .saisie.grid(row=0, column=0, sticky="EW")
     
            self.bout=Tkinter.Button(self, text="insert", command=lambda x="123to to789": self.insevent(x))
            self.bout.grid(row=1)
     
            self.saisie.focus_set()
            self.touche=None
     
        def quelletouche(self, event):
            self.touche=event
            print ' '
            print 'Dans quelletouche :', self.touche.char
     
        def veriftouche(self):
            print 'Passe par la validation'
            print ' '
            if (self.touche.char not in ListeAccents.keys()) or (self.touche.keysym == "BackSpace"):
                return True
            else:
                self.saisie.event_generate(ListeAccents[self.touche.char])
                return False
     
        def insevent(self, ch):
            for car in ch:
                self.saisie.event_generate(car)
     
    fen=Tkinter.Tk()
    app=Application(fen)
    ListeAccents = {' ':'_','é':'e','è':'e','ê':'e','ë':'e','æ':'ae','ã':'a','ä':'a','á':'a','à':'a','â':'a','ä':'a','ù':'','ô':'o','ö':'o','ç':'c','ï':'i','û':'','î':'i','ñ':'n','À':'A','Á':'A','Â':'A','Ã':'A','Ä':'A','Å':'A','Æ':'AE','Ç':'C','È':'E','É':'E','Ê':'E','Ë':'E','Ñ':'N','Ì':'I','Í':'I','Î':'I','Ï':'I','Ï':'I','Ò':'O','Ó':'O','Ô':'O','Õ':'O','Ö':'O','Ü':'','Û':'','Ú':'','Ù':'','Œ':'OE','œ':'oe'}
    fen.mainloop()
    Cela ne viens pas de l'event_generate en lui même puisque le bind capte un insert de la même manière.
    De même le premier event_generate est bien gérer.
    C'est bien la validation qui saute (voir les print) dés que je modifie self.saisie.car.

    Je suis obligé de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        def veriftouche(self):
            print 'Passe par la validation'
            print ' '
            if (self.touche.char not in ListeAccents.keys()) or (self.touche.keysym == "BackSpace"):
                return True
            else:
                self.saisie.event_generate(ListeAccents[self.touche.char])
                self.saisie.configure(validate='key',validatecommand=self.veriftouche)
                return False
    Pour retrouver ma validation.

    Avec mon code exemple cela donne :

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    from Tkinter import *
    from os import linesep
     
    ListeAccents = {' ':'_','é':'e','è':'e','ê':'e','ë':'e','æ':'ae','ã':'a','ä':'a','á':'a','à':'a','â':'a','ä':'a','ù':'','ô':'o','ö':'o','ç':'c','ï':'i','û':'','î':'i','ñ':'n','À':'A','Á':'A','Â':'A','Ã':'A','Ä':'A','Å':'A','Æ':'AE','Ç':'C','È':'E','É':'E','Ê':'E','Ë':'E','Ñ':'N','Ì':'I','Í':'I','Î':'I','Ï':'I','Ï':'I','Ò':'O','Ó':'O','Ô':'O','Õ':'O','Ö':'O','Ü':'','Û':'','Ú':'','Ù':'','Œ':'OE','œ':'oe'}
    # pas le dict pour ce code mais un copier/coller c'est plus facile
     
    class MonAppli_Globals():
        EntryChoixRep_StringVar = None # Je l'utilise aprés
     
    class mon_app(Tk):
        def C_Ok(self):
            print 'la suite'        
     
        def C_Quit(self):
            self.destroy()
     
        def quelletouche(self, event):
            self.touche=event
     
        def veriftouche(self):
            if (self.touche.char not in ListeAccents.keys()) or (self.touche.keysym == "BackSpace"):
                return True
            else:
                self.EntryChoixRep.event_generate(ListeAccents[self.touche.char])
                self.EntryChoixRep.configure(validate='key',validatecommand=self.veriftouche)
                return False
     
        def __init__(self,parent):
            Tk.__init__(self,parent)
            self.parent = parent
            self.initialize()
     
        def initialize(self, event = None):
            self.geometry("%dx%d+%d+%d" % (230,130, (self.winfo_screenwidth()-230)/2, (self.winfo_screenheight()-130)/2 ) )
            self.resizable(False,False)
            Label(self, fg="dark slate blue", text= linesep + "Texte à vérifier :").pack(side=TOP)
            MonAppli_Globals.EntryChoixRep_StringVar = StringVar()
            self.EntryChoixRep = Entry(self, bg="white", fg="dark slate blue", justify = "center", textvariable= MonAppli_Globals.EntryChoixRep_StringVar)
            self.EntryChoixRep.pack(side=TOP, pady=10)
            self.EntryChoixRep.configure(validate='key',validatecommand=self.veriftouche)
            self.EntryChoixRep.bind("<Key>", self.quelletouche)
            Frame(self, height=2, bd=1, relief=SUNKEN).pack(side=TOP, fill=X, padx=5, pady=5)
            Button(self, text="Valider", fg='dark slate blue', activebackground='white', activeforeground='#2a7aff', command = self.C_Ok).pack(side=LEFT, padx=10)
            Button(self, text="Annuler", fg='dark slate blue', activebackground='white', activeforeground='#2a7aff', command = self.C_Quit).pack(side=RIGHT, padx=10)
            self.EntryChoixRep.focus_set()
            self.bind('<Escape>', self.C_Quit )
     
    if __name__ == "__main__":
        app = mon_app(None)
        app.mainloop()
    Donc ta proposition fonctionne à merveille et je passe en résolu.

    Grand merci

  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
    Un print self.saisie.config() montre où est le problème : La modification de la self.touche.char passe validate à None :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        def quelletouche(self, event):
            self.touche=event
            print self.saisie.config()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    'validate': ('validate', 'validate', 'Validate', <index object at 0x8dede58>, 'none')
    'validatecommand': ('validatecommand', 'validateCommand', 'ValidateCommand', '', '147891380veriftouche')
    Donc validatecommand ne s'exécute plus.

    Encore merci.

  5. #5
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 478
    Points : 9 280
    Points
    9 280
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Comme certaines de tes découvertes m'avaient intrigué, j'ai essayé de voir si je pouvais filtrer certains caractères et les modifier "à la volée".

    Voilà le résultat:

    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
     
    #!/usr/bin/python
    # -*- coding:utf-8 -*-
     
    from __future__ import division
     
    import Tkinter
     
    ####################################################
    class Application(Tkinter.Frame):
     
        def __init__(self, master=None):
     
            Tkinter.Frame.__init__(self, master)
     
            self.grid()
            self.varsaisie = Tkinter.StringVar()
            self.varsaisie.set("")
            self.saisie=Tkinter.Entry(self,  background="white", width=50, textvariable=self.varsaisie)
     
            self.saisie.bind("<Key>", self.quelletouche)
     
            self.saisie.grid(row=0,column=0,padx=3, pady=6)
            self.saisie.focus_set()
     
            self.alpha1 = u"àÀâÂçÇéÉèÈêÊëËîÎïÏôÔùÙûÛüÜÿŸ"
            self.alpha2 = u"aAaAcCeEeEeEeEiIiIoOuUuUuUyY"
     
        def quelletouche(self, event):
            self.touche=event
            self.saisie.configure(validate="key",validatecommand=self.veriftouche)
     
        def veriftouche(self):
            i = self.alpha1.find(self.touche.char)
            if i>=0:
                self.saisie.event_generate(self.alpha2[i])
                return False
            else:
                return True
     
    ####################################################
    # lancement et affichage au centre de l'écran de l'application
    #
    if __name__ == "__main__":
        fen=Tkinter.Tk()
        fen.title(u"Saisie controlée")
        app=Application(fen)
        fen.mainloop()
    Ce programme test permet de remplacer chacun des caractères accentués par leur équivalent non accentué (y compris majuscule) au fur et à mesure qu'ils sont frappés.

    Comme tu peux voir, j'ai constaté aussi que le validate devait être réactivé à chaque fois. Aussi, je l'ai mis dans le "quelletouche()".

    Il suffit de changer alpha1 et 2 pour provoquer d'autres conversions, par exemple de minuscule en majuscule ou le contraire.

    Merci pour l'idée en tout cas: j'ajouterai cette solution à mon tuto.

    Tyrtamos

  6. #6
    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 tyrtamos,

    Avec l'unicode de self.alpha1 et self.alpha2 (pourquoi pour alpha2 ?) ton code bloque chez moi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Exception in Tkinter callback
    Traceback (most recent call last):
      File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1413, in __call__
        return self.func(*args)
      File "test14.py", line 33, in veriftouche
        i = self.alpha1.find(self.touche.char)
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
    Je suis obligé de faire un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    i = self.alpha1.find(unicode(self.touche.char, 'UTF-8'))
    Sinon j'aime bien l'idée qui m'évite d'utiliser ListeAccents qui est externe.

    @+

  7. #7
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 478
    Points : 9 280
    Points
    9 280
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    ...Avec l'unicode de self.alpha1 et self.alpha2 (pourquoi pour alpha2 ?) ton code bloque chez moi...
    Bizarre. Il doit y avoir des différences de configuration de nos Pythons. Je vais regarder ça de plus près.

    En ce qui me concerne, je travaille le plus possible en unicode en interne.

    Tyrtamos

  8. #8
    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
    Je pense que cela viens de chez moi. Je suis passer de la version 8.04 à 9.04 d'ubuntu le weekend dernier (avec passage python 2.5 > 2.6 donc) et je me retrouve avec des erreurs d'encodage dans des codes (ou ce qui y ressemble ) sans problèmes avant.
    Config de python dans la 9.04 ou version de python moins conciliante ? Je ne sais pas mais je suis encore en train de corriger tout cela

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

Discussions similaires

  1. Affichage texte lettre par lettre
    Par Yami no tenshi dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 03/09/2008, 13h22
  2. Afficher un texte lettre par lettre
    Par koKoTis dans le forum Flash
    Réponses: 2
    Dernier message: 11/12/2007, 21h14
  3. Comparer une chaîne lettre par lettre
    Par ero-sennin dans le forum C++Builder
    Réponses: 9
    Dernier message: 10/11/2007, 21h23
  4. Réponses: 6
    Dernier message: 23/01/2007, 17h20

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