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 :

répéter une action en boucle


Sujet :

Tkinter Python

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 147
    Points : 64
    Points
    64
    Par défaut répéter une action en boucle
    Bonjour,
    Je cherche à faire une coloration <<presque>> automatique du contenu du widget Text. Ce que j'aimerais, c'est que la commande syntaxe_couleur s'exécute toutes les 5 secondes par exemple mais ne m'empêche de continuer à écrire dans le widget Text.
    Suis-je obligé de passer par un thread? où y a-t-il une solution?
    Merci pour vos réponses;
    Gabriel
    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
    import tkinter
    import time
     
    def syntaxe_couleur(event=None):
        time.sleep(5)
        contents = t.get(1.0, tkinter.END)
        coordonnees=t.index(tkinter.INSERT) 
        t.delete("1.0",tkinter.END)
        t.insert("1.0",contents)
        t.mark_set(tkinter.INSERT, coordonnees)
        t.see(coordonnees)      
     
        nmbChar = tkinter.IntVar()
        lastPos = "1.0"
        while 1 :
                liste_noms="[0-9]"
                lastPos = t.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                if lastPos == "" :
                    break
                t.tag_add( 'commandes', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                lastPos = "%s + 1 chars" % lastPos
        t.tag_configure( 'commandes', foreground = 'red',font=("courier",10))
     
    root=tkinter.Tk()
    t=tkinter.Text(root)
    t.focus_set()
    t.pack()
    t.bind('<Control-m>',syntaxe_couleur)
    root.mainloop()

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Tk comme la plupart des GUI sont dits "event driven". En gros cela signifie que les "changements" de l'affichage et l'appel des fonctions associées au widgets affichés, au keyboard ou à la souris sont "evènements qui déclenchent l'appel à".

    Pour des raisons techniques, difficile de lancer "l'appel à" "dès que" car l'action déclenchée par un événement précédent est peut être encore "active". La machine va assez vite pour que lorsque vous cliquez çà réagisse mais impossible qu'elle oublie que vous avez cliqué parce que l'action précédente n'est pas encore terminée => naturellement, on empile les événements dans une liste et ils sont traités séquentiellement.

    => lorsqu'après avoir construit l'affichage on appelle .mainloop, on démarre la boucle de traitement de la liste d'évènements.

    Avec toute cette infrastructure, il est peux couteux de permettre au programmeur d'insérer ses propres évènements dans la "mainloop".

    Dans votre cas t.after ( 5000, syntaxe_couleur ) avec un repost de la même chose en sortie de syntaxe_couleur devrait suffire.

    Suis-je obligé de passer par un thread? où y a-t-il une solution?
    Comme syntaxe_couleur modifie l'état du widget text, vous ne pouvez pas passer par un thread!!!
    Relisez le paragraphe "Pour des raisons techniques" précédent: Si le GUI a été construit pour traiter les événements séquentiellement, c'est pour assurer, garantir la cohérence de son "état global".
    Avec l'exécution de syntaxe_couleur dans un thread diffférent de celle du GUI, vous ne pouvez plus assurer cette cohérence => bug.
    Note: Vous pouvez utiliser des threads, mais lorsque la thread doit parler avec le GUI, elle devra elle aussi "poster" un évènement i.e appeler .after_idle ou .after(0,...)

    Questions:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    contents = t.get(1.0, tkinter.END)
        coordonnees=t.index(tkinter.INSERT) 
        t.delete("1.0",tkinter.END)
        t.insert("1.0",contents)
        t.mark_set(tkinter.INSERT, coordonnees)
        t.see(coordonnees)
    Intuitivement, la mise en forme n'est importante que pour ce que l'utilisateur "voit" i.e. la partie affichée du texte qui n'en est qu'un sous ensemble.
    Il serait peut être "utile" de penser à séparer le bout de texte qu'on voit du texte sauvé dans le fichier.

    Je n'aime pas l'idée "toutes les 5s...": pourquoi ne pas faire cela au fur et à mesure que le texte est modifié?

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

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 147
    Points : 64
    Points
    64
    Par défaut
    Bonsoir,

    Je commence par répondre par le plus facile:
    Je n'aime pas l'idée "toutes les 5s...": pourquoi ne pas faire cela au fur et à mesure que le texte est modifié?
    En fait, il y a deux raisons - qui ne sont peut être pas valables... -
    Je pense que mon programme de coloration synthétique n'est pas performant (dans le code ci-dessus, il n'y avait qu'un bout). J'avais commencé par faire un root.bind('<KeyPress>',syntaxe_couleur) mais j'ai remarqué à l'usage, que le traitement pouvait s'avérer long (presque 1s) lorsque le fichier devient lourd ce qui est gênant lorsque l'on tape son texte...
    La deuxième raison, c'est que j'ai déjà <<réservé>> le '<keypress>' pour une complémentation automatique et je crains (peut-être à tort) qu'il y ait un <<conflit>> d'actions déclenchées par la même touche.
    Le sous programme complet pour la coloration de syntaxe est ci-dessous:
    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
        def syntaxe_couleur(self,event=None):
            id_onglet = self.ong.select()
            texte1 = self.fe.feuilles[id_onglet][1]
            contents = texte1.get(1.0, tkinter.END)
            coordonnees=texte1.index(tkinter.INSERT) 
            texte1.delete("1.0",tkinter.END)
            texte1.insert("1.0",contents)
            texte1.mark_set(tkinter.INSERT, coordonnees)
            texte1.see(coordonnees)      
     
            nmbChar = tkinter.IntVar()
            lastPos = "1.0"
            while 1 :
                  liste_noms="(\\\\)([a-zA-Z0-9]*)([\\\\+=\(\{\$\-&\\n\ \}\)\[\]_\^,?;.:/%])"
                  lastPos = texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'commandes', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            texte1.tag_configure( 'commandes', foreground = 'brown',font=("courier",10))
            lastPos = "1.0"
            while 1 :
                  liste_noms="(\\\\begin)|(\\\\end)|(\\\\\\\\)"
                  lastPos = texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'environnement', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            texte1.tag_configure( 'environnement', foreground = 'blue',font=("courier",10))
            lastPos = "1.0"
            while 1 :
                  liste_noms="[\{\(\[\|_\^@\)\]\}]"
                  lastPos = texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'delimitateur', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            texte1.tag_configure( 'delimitateur', foreground = 'dark orange',font=("Courier",10,"bold"))
            lastPos = "1.0"
            while 1 :
                  liste_noms=(r"(\\\()((.|\n)*?)(\\\))")
                  lastPos=texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'equation', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            lastPos = "1.0"
            while 1 :
                  liste_noms=(r"(\\\[)((.|\n)*?)(\\\])")
                  lastPos=texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'equation', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            lastPos = "1.0"
            while 1 :
                  liste_noms=(r"(\\<)((.|\n)*?)(\\>)")
                  lastPos=texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'equation', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            texte1.tag_configure( 'equation', foreground = 'purple',font=("Courier",10))        
            lastPos = "1.0"
            while 1 :
                  liste_noms="(\\\\\()|(\\\\\))|(\\\\\[)|(\\\\\])|(\\$)|([0-9<>])"
                  lastPos = texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'chiffre', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            texte1.tag_configure( 'chiffre', foreground = 'dark violet',font=("Courier",10,"bold"))        
            lastPos = "1.0"
            while 1 :
                  liste_noms="([^\\\\]|\\n)(%)([^\\n]*?)(\\n)"
                  lastPos = texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'commentaire', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            texte1.tag_configure( 'commentaire', foreground = 'dark gray',font=("Courier",10,"bold"))
    Moins facile à comprendre pour moi:
    Intuitivement, la mise en forme n'est importante que pour ce que l'utilisateur "voit" i.e. la partie affichée du texte qui n'en est qu'un sous ensemble.
    Il serait peut être "utile" de penser à séparer le bout de texte qu'on voit du texte sauvé dans le fichier.
    Je pensais avoir séparé le contenu du widget Text du contenu du fichier. Mais c'est peut-être là la non performance de mon programme de couleur de syntaxe mais j'ai trouvé que ce moyen pour réactualiser la couleur de syntaxe dans le widget Text.

    Enfin:
    Dans votre cas t.after ( 5000, syntaxe_couleur ) avec un repost de la même chose en sortie de syntaxe_couleur devrait suffire.
    Je ne connaissais pas l'action objet.after (je suis débutant en info et en python). Je vais essayer de l'appliquer. Cependant, s'il y a une solution plus efficace pour la coloration de syntaxe et qu'il n'y a pas de risques de conflit, je suis bien sûr plus intéressé par une coloration événementielle.

    Merci pour les réponses.
    Gabriel

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Je pensais avoir séparé le contenu du widget Text du contenu du fichier. Mais c'est peut-être là la non performance de mon programme de couleur de syntaxe mais j'ai trouvé que ce moyen pour réactualiser la couleur de syntaxe dans le widget Text.
    Pardon, je vous égare probablement car je n'avais pas "capté" que vous ne coloriez que la syntaxe.

    Cependant, s'il y a une solution plus efficace pour la coloration de syntaxe et qu'il n'y a pas de risques de conflit, je suis bien sûr plus intéressé par une coloration événementielle.
    Ne sachant trop jusqu'où vous voulez aller, je n'ai ni la prétention ni le temps de réfléchir à ce qui pourrait être efficace. Néanmoins, il y a sans doute de bonne idées à piocher ici ou là et peut être dans le code d'IDLE.
    IDLE est l'environnement de développement "intégré" à Python.
    Il est écrit en Python et construit avec tkinter.
    IDLE fait de la coloration de syntaxe pour les scripts python "édités" dans un widget text.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  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
    Bonjour,

    1) Oubliez les threads. Tkinter a déjà un gestionnaire d’événement, autant l'utiliser. Exemple sur votre 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
    import tkinter
     
    def syntaxe_couleur(event=None):
        contents = t.get(1.0, tkinter.END)
        coordonnees = t.index(tkinter.INSERT) 
        t.delete("1.0", tkinter.END)
        t.insert("1.0", contents)
        t.mark_set(tkinter.INSERT, coordonnees)
        t.see(coordonnees)      
     
        nmbChar = tkinter.IntVar()
        lastPos = "1.0"
        while 1 :
                liste_noms="[0-9]"
                lastPos = t.search(liste_noms, index=lastPos, stopindex=tkinter.END,
                                   regexp=1, count=nmbChar )
                if lastPos == "" :
                    break
                t.tag_add('commandes', lastPos, "%s + %d chars" % (lastPos,
                                                                   nmbChar.get()))
                lastPos = "%s + 1 chars" % lastPos
        t.tag_configure('commandes', foreground='red', font=("courier", 10))
        t.after(5, syntaxe_couleur)
     
    root = tkinter.Tk()
    t = tkinter.Text(root)
    t.focus_set()
    t.pack()
    t.after(5, syntaxe_couleur)
    root.mainloop()
    Attention:
    widget.after(temps_en_ms, calllback)
    Si votre callback est long ne bouclez pas trop vite.

    2) Oubliez time.spleep(x) qui est bloquant pour le code.

    Ensuite:
    Je pense que mon programme de coloration synthétique n'est pas performant (dans le code ci-dessus, il n'y avait qu'un bout). J'avais commencé par faire un root.bind('<KeyPress>',syntaxe_couleur) mais j'ai remarqué à l'usage, que le traitement pouvait s'avérer long (presque 1s) lorsque le fichier devient lourd ce qui est gênant lorsque l'on tape son texte...
    La deuxième raison, c'est que j'ai déjà <<réservé>> le '<keypress>' pour une complémentation automatique et je crains (peut-être à tort) qu'il y ait un <<conflit>> d'actions déclenchées par la même touche.
    Pour ce qui est de la performance en terme de vitesse les regex ne sont pas réputés pour cela. D'autant plus si vous les cumulez.
    Pourquoi ne pas 'planifier' tout cela ? Histoire de laisser souffler les autres.
    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
    import tkinter
     
     
    def syntaxe_chiffre():
        liste_noms="[0-9]"
        lastPos = "1.0"
        while 1:
                lastPos = t.search(liste_noms, index=lastPos, stopindex=tkinter.END,
                                   regexp=1, count=nmbChar )
                if not lastPos:
                    break
                t.tag_add('chiffre', lastPos, "%s + %d chars" % (lastPos,
                                                                   nmbChar.get()))
                lastPos = "%s + 1 chars" % lastPos
        t.tag_configure('chiffre', foreground='red', font=("courier", 10))
        t.after(50, syntaxe_lettres) # <<<<< On laisse 'souffler'
     
    def syntaxe_lettres():
        liste_noms = "[a-zA-Z]"
        lastPos = "1.0"
        while 1 :
            lastPos = t.search(liste_noms, index=lastPos, stopindex=tkinter.END,
                               regexp=1, count=nmbChar)
            if not lastPos:
                break
            t.tag_add( 'lettre', lastPos, "%s + %d chars" % (lastPos,
                                                                nmbChar.get()))
            lastPos = "%s + 1 chars" % lastPos
        t.tag_configure( 'lettre', foreground='blue', font=("courier",10))
        # after suivant ici
    # Etc...
     
    def completion(event):
        # Code de completion
        t.after(50, syntaxe_chiffre) # Ou plutot directement syntaxe_chiffre()
     
    root = tkinter.Tk()
    t = tkinter.Text(root)
    t.focus_set()
    t.pack()
    nmbChar = tkinter.IntVar()
    t.bind('<KeyPress>', completion)
    root.mainloop()
    @+
    Merci d'utiliser le forum pour les questions techniques.

  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
    Un exemple en continu:

    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
    import tkinter
     
     
    def syntaxe_chiffre():
        if not syntaxe_flag.get():
            # S'il n'y a pas de verif en cours je prend la main
            syntaxe_flag.set(1)
        else:
            # Sinon j'attend
            t.after(500, syntaxe_chiffre)
            # Et on n'execute pas le reste
            return
        liste_noms="[0-9]"
        lastPos = "1.0"
        while 1:
                lastPos = t.search(liste_noms, index=lastPos, stopindex=tkinter.END,
                                   regexp=1, count=nmbChar )
                if not lastPos:
                    break
                t.tag_add('chiffre', lastPos, "%s + %d chars" % (lastPos,
                                                                   nmbChar.get()))
                lastPos = "%s + 1 chars" % lastPos
        t.tag_configure('chiffre', foreground='red', font=("courier", 10))
        # On rend la main
        syntaxe_flag.set(0)
        # Jusqu'au prochain tour
        t.after(500, syntaxe_chiffre)
     
    def syntaxe_lettres():
        if not syntaxe_flag.get(): # Verifier directement (not) pour prendre directement la main ?
            # S'il n'y a pas de verif en cours je prend la main
            syntaxe_flag.set(1)
        else:
            # Sinon j'attend
            t.after(500, lettres)
            # Et on n'execute pas le reste
            return
        liste_noms = "[a-zA-Z]"
        lastPos = "1.0"
        while 1 :
            lastPos = t.search(liste_noms, index=lastPos, stopindex=tkinter.END,
                               regexp=1, count=nmbChar)
            if not lastPos:
                break
            t.tag_add( 'lettre', lastPos, "%s + %d chars" % (lastPos,
                                                                nmbChar.get()))
            lastPos = "%s + 1 chars" % lastPos
        t.tag_configure( 'lettre', foreground='blue', font=("courier",10))
        # On rend la main
        syntaxe_flag.set(0)
        # Jusqu'au prochain tour
        t.after(500, syntaxe_lettres)
     
     
    root = tkinter.Tk()
    t = tkinter.Text(root)
    t.focus_set()
    t.pack()
    nmbChar = tkinter.IntVar()
    syntaxe_flag = tkinter.BooleanVar(0)
    t.after(50, syntaxe_chiffre)
    t.after(100, syntaxe_lettres)
    root.mainloop()
    Mais je n'aime pas trop car on a pas 'la main' sur les events. Passer par une visit_method / poller_routine ? Sans doute mais pas ce matin

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

  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
    Peut être plus 'souple':

    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
    import tkinter
     
     
    def syntaxe_chiffre():
        # On prend la main
        syntaxe_flag.set(1)
        liste_noms="[0-9]"
        lastPos = "1.0"
        while 1:
                lastPos = t.search(liste_noms, index=lastPos, stopindex=tkinter.END,
                                   regexp=1, count=nmbChar )
                if not lastPos:
                    break
                t.tag_add('chiffre', lastPos, "%s + %d chars" % (lastPos,
                                                                   nmbChar.get()))
                lastPos = "%s + 1 chars" % lastPos
        t.tag_configure('chiffre', foreground='red', font=("courier", 10))
        # On rend la main
        syntaxe_flag.set(0)
     
    def syntaxe_lettres():
        # On prend la main
        syntaxe_flag.set(1)
        liste_noms = "[a-zA-Z]"
        lastPos = "1.0"
        while 1 :
            lastPos = t.search(liste_noms, index=lastPos, stopindex=tkinter.END,
                               regexp=1, count=nmbChar)
            if not lastPos:
                break
            t.tag_add( 'lettre', lastPos, "%s + %d chars" % (lastPos,
                                                                nmbChar.get()))
            lastPos = "%s + 1 chars" % lastPos
        t.tag_configure( 'lettre', foreground='blue', font=("courier",10))
        # On rend la main
        syntaxe_flag.set(0)
     
    def func_caller(idx, timer, base_timer, func_to_use):
        # base_timer: le temps d'attente minimun entre chaque vérification.
        # On pourrais utliser 
        if syntaxe_flag.get():
            # Une vérification en cours
            # On rallonge le timer puisque l'on est trop 'rapide'
            timer += 50
            # On attend qu'elle libère syntaxe_flag
            t.after(timer, lambda: func_caller(idx, timer, base_timer, func_to_use))
            # Et on n'execute pas le reste
            return
        # On reajuste le timer au cas ou le texte soit plus court. ie cut.
        if timer < base_timer:
            timer -= 50
        # Lancement de la fonction
        func_to_use[idx]()
        # Au prochain
        idx += 1
        if idx > len(func_to_use)-1:
            idx = 0
        t.after(timer, lambda: func_caller(idx, timer, base_timer, func_to_use))
     
     
    root = tkinter.Tk()
    t = tkinter.Text(root)
    t.focus_set()
    t.pack()
    nmbChar = tkinter.IntVar()
    # flag d'une utilisation en cours
    syntaxe_flag = tkinter.BooleanVar(0)
    # Lancement de la 'boucle'.
    func_caller(0, 500, 500, (syntaxe_chiffre, syntaxe_lettres))
    root.mainloop()
    A vous de définir base_timer suivant vos tests
    Merci d'utiliser le forum pour les questions techniques.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 147
    Points : 64
    Points
    64
    Par défaut
    Bonjour,

    Bon, je vais essayer de digérer tout çà. Si j'ai bien compris, vous proposez de <<séquencer>> la coloration synthétique avec des délais et des tests tels que la séquence suivante ne peut démarrer avant la fin de la précédente.

    Je vais tester le tout. Je retiens aussi que la recherche par expression régulière est gourmande en temps. Je vais voir si dans certaines situations, je peux m'en passer.

    Enfin j'ai pensé aussi que je pouvais rajouter deux variables à syntaxe_couleur du type index_du début, index_de_fin afin qu'il ne fasse les modifications uniquement entre ces deux balises.

    Merci.

    Gabriel

  9. #9
    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
    A vrais dire c'est plus séparer ce qui est bloquant (timing des regex, time, while et autre) ou les plutôt remplacer par le gestionnaire d’événement de Tkinter, dans le style (sans doute pas au points)

    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
    import tkinter as tk
    import tkinter.filedialog as tkFD
    import os
     
    def verif_syntaxe(index, regs):
        syntaxe_flag.set(1)
        lastPos = index
        liste_noms = regs[0]
        color = regs[1]
        tag = regs[2]
        lastPos = t.search(liste_noms, index=lastPos, stopindex=tk.END,
                           regexp=1, count=nmbChar)
        if lastPos:
            t.tag_add(tag, lastPos, "%s + %d chars" % (lastPos, nmbChar.get()))
            lastPos = "%s + 1 chars" % lastPos
            t.after(1, lambda: verif_syntaxe(lastPos, (liste_noms, color, tag)))
        else:
            t.tag_configure(tag, foreground=color, font=("courier", 10))
            syntaxe_flag.set(0)
     
    def func_caller(idx, timer, base_timer, regs):
        if syntaxe_flag.get():
            timer += 1
            t.after(timer, lambda: func_caller(idx, timer, base_timer, regs))
            return
        elif timer > base_timer:
            timer -= 1
        verif_syntaxe("1.0", regs[idx])
        idx += 1
        if idx > len(regs)-1:
            idx = 0
        t.after(timer, lambda: func_caller(idx, timer, base_timer, regs))
     
    def open_file():
        repertoire = os.path.expanduser('~')
        name = tkFD.askopenfilename(initialdir=repertoire,
                                    filetypes = [("Fichiers Texte","*.txt"), 
                                                 ("Fichiers Python","*.py"),])
        if name:
            with open(name, "r") as f:
                t.insert(tk.INSERT, f.read())
        t.update()
     
    root = tk.Tk()
    f = tk.Frame(root)
    geoargs = {'fill':'both', 'padx':5, 'pady':5}
    f.pack(side=tk.BOTTOM, **geoargs)
    tk.Button(f, text='Open File', command=open_file).pack(side=tk.LEFT, **geoargs)
    tk.Button(f, text='Quit', command=root.quit).pack(side=tk.RIGHT, **geoargs)
    xscrollbar = tk.Scrollbar(root, orient=tk.HORIZONTAL)
    xscrollbar.pack(side=tk.BOTTOM, fill=tk.X)
    yscrollbar = tk.Scrollbar(root)
    yscrollbar.pack(side=tk.RIGHT, fill=tk.Y)
    t = tk.Text(root, wrap=tk.NONE, xscrollcommand=xscrollbar.set,
                yscrollcommand=yscrollbar.set)
    t.pack()
    xscrollbar.config(command=t.xview)
    yscrollbar.config(command=t.yview)
    nmbChar = tk.IntVar()
    syntaxe_flag = tk.BooleanVar(0)
    regs = (("[a-zA-Z]", 'red', 'letters'), ("[0-9]", 'blue', 'numbers'))
    func_caller(0, 10, 10, regs)
    t.focus_set()
    root.mainloop()
    Vous remarquerez que c'est moins bloquant.
    Merci d'utiliser le forum pour les questions techniques.

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 147
    Points : 64
    Points
    64
    Par défaut
    Bonjour,

    J'ai repris mon sous-programme. Et au lieu de répéter à chaque fois les while accompagnées de recherche par expressions régulières, j'ai découpé le programme en discussion
    Si trouvé ça alors faire sinon si ...
    Le programme devient long, mais l'exécution beaucoup plus courte, puisque je n'ai plus qu'un seule while et les expressions régulières sont moins lourdes.

    Merci pour vos réponses.

    Gabriel

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

Discussions similaires

  1. [XL-2007] Répéter une action plusieurs fois
    Par Guiggs dans le forum Macros et VBA Excel
    Réponses: 11
    Dernier message: 08/07/2013, 18h25
  2. Exécuter une action en boucle pendant un temps donné
    Par greg_78 dans le forum Général Python
    Réponses: 10
    Dernier message: 07/10/2010, 07h09
  3. Répéter une action monadique
    Par limestrael dans le forum Haskell
    Réponses: 6
    Dernier message: 17/12/2009, 22h34
  4. répéter une action
    Par Lubovic dans le forum VB.NET
    Réponses: 10
    Dernier message: 27/01/2009, 19h26
  5. Réponses: 4
    Dernier message: 15/06/2006, 10h05

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