88 votes

Comment puis-je obtenir un rappel d'événement lorsqu'un widget Entry Tkinter est modifié?

Exactement comme le dit la question. Les widgets Text ont l'événement <>, mais les widgets Entry ne semblent pas l'avoir.

3voto

Oppy Points 855

J'utilise Python 3.6 et je n'ai pas réussi à faire fonctionner .trace. Le code suivant permet d'accepter ou de modifier une valeur par défaut de StringVar. on_changed est appelé lorsque la touche de retour est pressée.

from tkinter import Tk, LEFT, BOTH, StringVar
from tkinter.ttk import Entry, Frame

class Example(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.initUI()

    def initUI(self):
        self.parent.title("Entry")
        self.pack(fill=BOTH, expand=1)
        self.contents = StringVar()
        # donner à StringVar une valeur par défaut
        self.contents.set('test')
        self.entry = Entry(self)
        self.entry.pack(side=LEFT, padx=15)
        self.entry["textvariable"] = self.contents
        self.entry.bind('', self.on_changed)

    def on_changed(self, event):
        print('contents: {}'.format(self.contents.get()))
        return True

def main():
    root = Tk()
    ex = Example(root)
    root.geometry("250x100+300+300")
    root.mainloop()

if __name__ == '__main__':
    main()

2voto

Je connais une autre variante.

avant d'entrer le code, il serait préférable d'expliquer le chemin du codage : lire ici

et voici mon code:

from Tkinter import *

class ttt:
   def __init__(self):
      self.str1 = StringVar()
      self.e1 = Entry(root, textvariable=self.str1)
      self.str1.trace('w', self.callback_1)
      self.e1.pack()

      self.str2 = StringVar()
      self.e2 = Entry(root, textvariable=self.str2, state='readonly')
      self.e2.pack()

      self.str3 = StringVar()
      self.e3 = Entry(root, textvariable=self.str3, state='readonly')
      self.e3.pack()

      bt = Button(root, text = 'ещё', command = self.callback_2)
      bt.pack()

   def callback_1(self, name='', index='', mode=''):
      tmp = self.str1.get()
      if tmp:
         self.str2.set(int(tmp) * 6)
         print self.str2.get()

   def callback_2(self, name='', index='', mode=''):
      tmp = self.str1.get()
      if tmp:
         self.str3.set(int(tmp) * 6)
         print self.str3.get()   

root = Tk()
t = ttt()
root.mainloop()

il y a 2 variantes : en appuyant sur le bouton et en entrant dans l'entrée. maintenant vous pouvez choisir n'importe quelle variante

0voto

Conrad B Points 108

J'ai trouvé que l'utilisation de la Validation TK intégrée correspondait mieux à mon niveau de compétence débutant en python. La validation d'un élément Entry n'est pas bien documentée dans tkinter lui-même, vous devez utiliser une méthode register() pour définir un rappel, et en toujours retournant True à partir du rappel de validation enregistré, vous pouvez recevoir une notification.

def filter_callback(self,nouvelle_valeur):
    print(nouvelle_valeur)
    # doit retourner vrai car nous voulons que les événements de validation continuent à arriver
    return(True)

def __init__(self,root)
    self.edit_filter = ttk.Entry(root)
    # %d = Type d'action (1=insertion, 0=suppression, -1 pour les autres)
    # %i = index du caractère de la chaîne à insérer/supprimer, ou -1
    # %P = valeur de l'entrée si la modification est autorisée
    # %s = valeur de l'entrée avant l'édition
    # %S = la chaîne de texte insérée ou supprimée, le cas échéant
    # %v = le type de validation actuellement défini
    # %V = le type de validation qui a déclenché le rappel
    #      (clé, focusin, focusout, forcé)
    # %W = le nom tk du widget
    vcmd = (self.edit_filter.register(self.filter_callback), "%P")
    # notifier uniquement les pressions de touche
    self.edit_filter.config(validate = "key", validatecommand = vcmd) 

(code illustratif seulement)

Exemple de réponse ici Validation interactive du contenu du widget Entry dans tkinter, et quelques docs sur les événements ici https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/entry-validation.html. Ce n'est pas moins de code que l'utilisation de trace, mais peut être plus facile à suivre pour certains débutants et à construire.

0voto

Youstanzr Points 436

Ceci est mon interprétation basée sur la réponse de @Avi ba. Je l'ai simplifié en ajoutant un setter et un getter pour la variable de texte. J'ai également évité d'utiliser StrinVar.

class CustomEntry(ttk.Entry):
    def __init__(self, parent, valueChangeCallback=lambda x: print(x), **kwargs):
        super().__init__(parent, **kwargs)

        # lier la fonction de rappel lorsque la valeur du texte est changée
        self.bind("", lambda e: valueChangeCallback(self.text))

    @property
    def text(self) -> str:
        return self.get()

    @text.setter
    def text(self, value) -> None:
        self.delete(0, 'end')
        self.insert(0, value)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X