Genau wie die Frage sagt. Text
-Widgets haben das <<Modified>>
-Ereignis, aber Entry
-Widgets erscheinen nicht.
Fügen Sie Ihrem Entry-Widget eine Tkinter-String-Variable hinzu. Binden Sie Ihren Callback mit der Trace-Methode an die StringVar.
from Tkinter import *
def callback(sv):
print sv.get()
root = Tk()
sv = StringVar()
sv.trace("w", lambda name, index, mode, sv=sv: callback(sv))
e = Entry(root, textvariable=sv)
e.pack()
root.mainloop()
Zum Zeitpunkt des Schreibens (2017, Python 3.6, tkinter Version 8.6.6) legen die Dokumente nahe, dass .trace
veraltet ist. Das vorgeschlagene Formular scheint jetzt zu sein:
sv.trace_add("write", callback)
Dies funktioniert sehr gut, wenn Sie eine Benachrichtigung erhalten möchten, wenn die Variable geändert wird. Meine Anwendung möchte jedoch nur eine Benachrichtigung, wenn der Benutzer den Text bearbeitet hat. Ich fand, dass der Mechanismus der "Validierung" gut funktioniert, um hier gut zu funktionieren:
from tkinter import *
root = Tk()
sv = StringVar()
def callback():
print(sv.get())
return True
e = Entry(root, textvariable=sv, validate="focusout", validatecommand=callback)
e.grid()
e = Entry(root)
e.grid()
root.mainloop()
Dadurch wird callback
aufgerufen, wenn das Eintrags-Widget den Fokus verliert (ich habe ein Widget für den zweiten Eintrag hinzugefügt, sodass das erste Widget tatsächlich den Fokus verlieren kann!)
Danke Steven! Russell Owens Tkinter Folklore erläutert, wie der StringVar-Wert direkt aus dem Namensargument (PY_VAR #) mithilfe von globalgetvar () abgerufen wird, jedoch nicht, wie der Name einem Widget zugeordnet wird. Ihre Lambda-Methode zum Ändern der Callback-Args ist wie Zauberei (zumindest für uns Python-Neulinge).
Wenn es mehr als einen Eintrag gibt, ist es oft notwendig, nicht nur den Wert zu kennen, sondern auch, welcher Eintrag geändert wurde. Das folgende Beispiel (Python3) übergibt leicht ein Beispiel von Steven und übergibt einen Index, mit dem mehrere Einträge verfolgt werden können.
from tkinter import Tk, Frame, Label, Entry, StringVar
class Fruitlist:
def entryupdate(self, sv, i):
print(sv, i, self.fruit[i], sv.get())
def __init__(self, root):
cf = Frame(root)
cf.pack()
self.string_vars = []
self.fruit = ("Apple", "Banana", "Cherry", "Date")
for f in self.fruit:
i = len(self.string_vars)
self.string_vars.append(StringVar())
self.string_vars[i].trace("w", lambda name, index, mode, var=self.string_vars[i], i=i:
self.entryupdate(var, i))
Label(cf, text=f).grid(column=2, row=i)
Entry(cf, width=6, textvariable=self.string_vars[i]).grid(column=4, row=i)
root = Tk()
root.title("EntryUpdate")
app = Fruitlist(root)
root.mainloop()
Warum müssen Sie wissen, wann der Eintrag geändert wurde?
Wahrscheinlich brauchen Sie ein anderes Verhalten:
In diesem Fall können Sie einfach die Eingabetaste verwenden
self.entry.bind('<Return>', self.on_enter)
def on_enter(self, key_info):
text = self.entry.get()
Sie können auch das KeyRelease-Ereignis verwenden, das jedes Mal ausgelöst wird, wenn der Benutzer auf das Widget klickt.
Dann können Sie nach Änderungen filtern.
from tkinter import *
from tkinter import ttk
class GUI():
def __init__(self):
self.root = Tk()
self.sv = StringVar()
self.prevlaue=''
#entry
self.entry = ttk.Entry(self.root, width=30, textvariable =self.sv)
self.entry.grid(pady=20,padx=20)
self.entry.bind("<KeyRelease>", self.OnEntryClick) #keyup
self.root.mainloop()
def OnEntryClick(self, event):
value=self.sv.get().strip()
changed = True if self.prevlaue != value else False
print(value, 'Text has changed ? {}'.format(changed))
self.prevlaue = value
#create the gui
GUI()
Ich hoffe, es hilft.
Ich benutze Python 3.6 und konnte .trace nicht zum Laufen bringen. Mit dem folgenden Code kann ein Standardwert von StringVar akzeptiert oder bearbeitet werden. on_changed wird aufgerufen, wenn die Return-Taste gedrückt wird.
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()
# give the StringVar a default value
self.contents.set('test')
self.entry = Entry(self)
self.entry.pack(side=LEFT, padx=15)
self.entry["textvariable"] = self.contents
self.entry.bind('<Key-Return>', 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 __== '__main__':
main()
Ich kenne andere Variante.
bevor ich den Code eingebe, könnte ich den Pfad der Kodierung besser erklären: read here
und es gibt meinen 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()
es gibt 2 Varianten: Durch Drücken der Taste und Eingabe zum Eintrag . Jetzt können Sie eine beliebige Variante auswählen