【发布时间】:2011-07-01 13:49:24
【问题描述】:
正如问题所说。 Text 小部件具有 <<Modified>> 事件,但 Entry 小部件似乎没有。
【问题讨论】:
正如问题所说。 Text 小部件具有 <<Modified>> 事件,但 Entry 小部件似乎没有。
【问题讨论】:
将 Tkinter StringVar 添加到您的 Entry 小部件。使用 trace 方法将您的回调绑定到 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()
【讨论】:
print 和 Tkinter 需要为 Python 3 更改导入;lambda 将保持不变)。您将看到代码按预期运行。 lambda 表达式类似于def anonymous(name, index, mode, sv=sv):return callback(sv),只是它是一个表达式,而不是一个语句。 StringVar.trace 使用我们忽略的不需要的参数(名称、索引、模式)调用它的回调,而是对 StringVar 本身(sv)进行闭包,然后我们在回调中使用它。
= 视为将参数名称与默认值分开,而是将其视为参数名称和传递给该参数的值。
在撰写本文时(2017,Python 3.6,tkinter 版本 8.6.6),文档建议 .trace 已弃用。现在建议的形式似乎是:
sv.trace_add("write", callback)
如果您希望在变量更改时得到通知,这非常有效。但是,我的应用程序只希望在用户完成文本编辑时得到通知。我发现捎带“验证”机制在这里可以很好地工作:
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()
每当入口小部件失去焦点时,这将调用callback(我添加了第二个入口小部件,因此第一个实际上可以失去焦点!)
【讨论】:
谢谢史蒂文! Russell Owen 的 Tkinter Folklore 解释了如何使用 globalgetvar() 直接从名称参数 (PY_VAR#) 中获取 StringVar 值,而不是如何将名称映射到小部件。您更改回调参数的 lambda 方法就像魔术一样(至少对我们 Python 新手来说)。
当有多个条目时,通常不仅需要知道值,还需要知道更改了哪个条目。稍微扩展一下 Steven 的示例,以下 (Python3) 传递了一个索引,该索引可用于跟踪多个条目。
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()
【讨论】:
您还可以使用每次用户单击小部件时都会触发的 KeyRelease 事件。
您可以过滤更改。
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()
希望对你有帮助。
【讨论】:
我使用 Python 3.6,但无法让 .trace 工作。以下代码允许接受或编辑 StringVar 的默认值。 on_changed 在按下返回键时被调用。
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 __name__ == '__main__':
main()
【讨论】:
我知道其他变种。
在我输入代码之前,它可以更好地解释编码路径:阅读here
还有我的代码:
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()
有 2 种变体:按下按钮并进入。 现在您可以选择任何变体
【讨论】:
我已经能够使用<FocusOut> 事件来做我需要的事情。这是一个示例:
import tkinter
from tkinter import ttk
def doSomething(event):
text = event.widget.get()
print(text)
window = tkinter.Tk()
testEntry = ttk.Entry(window)
testEntry.bind('<FocusOut>', doSomething)
testEntry.grid(column=0,row=0)
thingEntry = ttk.Entry(window)
thingEntry.bind('<FocusOut>', doSomething)
thingEntry.grid(column=0,row=1)
startButton = ttk.Button(window,text='OK',command=lambda: print('click'))
startButton.grid(column=0,row=2, sticky='W')
window.mainloop()
print('Bye Bye')
重要的部分是:
def doSomething(event):
text = event.widget.get()
print(text)
testEntry.bind('<FocusOut>', doSomething)
使用Entry.bind(event,function),您可以附加一个事件侦听器,在本例中为doSomething 函数。该函数获取一个参数,一个Event 对象。反过来,您可以使用 event.widget.get() 阅读 Entry 小部件中的内容。
每次您留下Entry,它的值都会被打印出来。这包括单击按钮时。从测试中可以看到,按钮的事件是在Entry的事件之后触发的,
【讨论】:
我发现使用内置的 TK 验证更适合我的 Python 技能初学者水平。 tkinter 本身没有很好地记录 Entry 元素的验证,您必须使用 register() 方法来设置回调,并且通过 always 从注册的验证回调中返回 True,您可以获得通知。
def filter_callback(self,new_value):
print(new_value)
# must return true since we want the validation events to keep coming
return(True)
def __init__(self,root)
self.edit_filter = ttk.Entry(root)
# %d = Type of action (1=insert, 0=delete, -1 for others)
# %i = index of char string to be inserted/deleted, or -1
# %P = value of the entry if the edit is allowed
# %s = value of entry prior to editing
# %S = the text string being inserted or deleted, if any
# %v = the type of validation that is currently set
# %V = the type of validation that triggered the callback
# (key, focusin, focusout, forced)
# %W = the tk name of the widget
vcmd = (self.edit_filter.register(self.filter_callback), "%P")
# notify key presses only
self.edit_filter.config(validate = "key", validatecommand = vcmd)
(仅说明性代码)
Interactively validating Entry widget content in tkinter 此处为示例答案,https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/entry-validation.html 此处为事件的一些文档。它的代码并不比使用 trace 少,但对于一些初学者来说可能更容易遵循和构建。
【讨论】: