Den*_*aia 12 python events tkinter
我正在使用Python Tkinter,而且我希望onchange从其他工具包/语言中获得相当于的事件.我希望每当用户更新某些小部件的状态时运行代码.
就我而言,我有很多Entry,Checkbutton,Spinbox和Radiobutton小部件.每当这些更改中的任何一个,我想运行我的代码(在这种情况下,更新另一个面板上的文本框).
(只需记住用户可以使用鼠标或键盘与这些小部件进行交互,甚至使用Ctrl + V粘贴文本)
I_d*_*hon 10
我认为正确的方法是使用trace已分配给窗口小部件的tkinter变量.
例如...
import tkinter
root = tkinter.Tk()
myvar = tkinter.StringVar()
myvar.set('')
mywidget = tkinter.Entry(root,textvariable=myvar,width=10)
mywidget.pack()
def oddblue(a,b,c):
if len(myvar.get())%2 == 0:
mywidget.config(bg='red')
else:
mywidget.config(bg='blue')
mywidget.update_idletasks()
myvar.trace('w',oddblue)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)
该w每当有人写(更新)的变量,它会发生,每次有人在输入构件写的东西在跟踪告诉Tkinter的,做的oddblue.跟踪总是将三个值传递给您列出的任何函数,因此您需要在函数中期望它们a,b,c.我通常不会对它们做任何事情,因为无论如何我都需要在本地定义.从我可以告诉的a是变量对象,b是空白(不确定为什么),并且c是跟踪模式(即w).
我将如何解决这个问题使用Tcl将确保该checkbutton,纺纱器和单选按钮部件都与一个数组变量相关.然后我会把痕迹,这将导致一个函数来进行变量写入每次叫阵列上.Tcl使这个微不足道.
不幸的是,Tkinter不支持使用Tcl阵列.幸运的是,这也很容易破解.如果你喜欢冒险,尝试下面的代码.
来自完整的披露部门:我今天早上在大约半小时内把它扔到了一起.我还没有在任何实际代码中使用过这种技术.但是,我无法抗拒挑战,想弄清楚如何在Tkinter中使用数组.
import Tkinter as tk
class MyApp(tk.Tk):
'''Example app that uses Tcl arrays'''
def __init__(self):
tk.Tk.__init__(self)
self.arrayvar = ArrayVar()
self.labelvar = tk.StringVar()
rb1 = tk.Radiobutton(text="one", variable=self.arrayvar("radiobutton"), value=1)
rb2 = tk.Radiobutton(text="two", variable=self.arrayvar("radiobutton"), value=2)
cb = tk.Checkbutton(text="checked?", variable=self.arrayvar("checkbutton"),
onvalue="on", offvalue="off")
entry = tk.Entry(textvariable=self.arrayvar("entry"))
label = tk.Label(textvariable=self.labelvar)
spinbox = tk.Spinbox(from_=1, to=11, textvariable=self.arrayvar("spinbox"))
button = tk.Button(text="click to print contents of array", command=self.OnDump)
for widget in (cb, rb1, rb2, spinbox, entry, button, label):
widget.pack(anchor="w", padx=10)
self.labelvar.set("Click on a widget to see this message change")
self.arrayvar["entry"] = "something witty"
self.arrayvar["radiobutton"] = 2
self.arrayvar["checkbutton"] = "on"
self.arrayvar["spinbox"] = 11
self.arrayvar.trace(mode="w", callback=self.OnTrace)
def OnDump(self):
'''Print the contents of the array'''
print self.arrayvar.get()
def OnTrace(self, varname, elementname, mode):
'''Show the new value in a label'''
self.labelvar.set("%s changed; new value='%s'" % (elementname, self.arrayvar[elementname]))
class ArrayVar(tk.Variable):
'''A variable that works as a Tcl array variable'''
_default = {}
_elementvars = {}
def __del__(self):
self._tk.globalunsetvar(self._name)
for elementvar in self._elementvars:
del elementvar
def __setitem__(self, elementname, value):
if elementname not in self._elementvars:
v = ArrayElementVar(varname=self._name, elementname=elementname, master=self._master)
self._elementvars[elementname] = v
self._elementvars[elementname].set(value)
def __getitem__(self, name):
if name in self._elementvars:
return self._elementvars[name].get()
return None
def __call__(self, elementname):
'''Create a new StringVar as an element in the array'''
if elementname not in self._elementvars:
v = ArrayElementVar(varname=self._name, elementname=elementname, master=self._master)
self._elementvars[elementname] = v
return self._elementvars[elementname]
def set(self, dictvalue):
# this establishes the variable as an array
# as far as the Tcl interpreter is concerned
self._master.eval("array set {%s} {}" % self._name)
for (k, v) in dictvalue.iteritems():
self._tk.call("array","set",self._name, k, v)
def get(self):
'''Return a dictionary that represents the Tcl array'''
value = {}
for (elementname, elementvar) in self._elementvars.iteritems():
value[elementname] = elementvar.get()
return value
class ArrayElementVar(tk.StringVar):
'''A StringVar that represents an element of an array'''
_default = ""
def __init__(self, varname, elementname, master):
self._master = master
self._tk = master.tk
self._name = "%s(%s)" % (varname, elementname)
self.set(self._default)
def __del__(self):
"""Unset the variable in Tcl."""
self._tk.globalunsetvar(self._name)
if __name__ == "__main__":
app=MyApp()
app.wm_geometry("400x200")
app.mainloop()
Run Code Online (Sandbox Code Playgroud)
您可以通过三种不同的方式来执行相同的操作:
1-使用内置的“命令”配置,就像在按钮上使用的配置一样
import tkinter as tk
from tkinter import messagebox as tk_messagebox
def spinbox1_callback():
tk_messagebox.showinfo("Spinbox callback", "You changed the spinbox.")
if __name__ == "__main__":
master = tk.Tk()
spinbox1 = tk.Spinbox(master, from_=0, to=10, command=spinbox1_callback)
spinbox1.pack()
tk.mainloop()
Run Code Online (Sandbox Code Playgroud)
2-使用事件绑定捕获特定事件: http://web.archive.org/web/20190712094613/http ://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
import tkinter as tk
from tkinter import messagebox as tk_messagebox
root = tk.Tk()
def callback(event):
tk_messagebox.showinfo("clicked at", event.x, event.y)
frame = tk.Frame(root, width=100, height=100)
frame.bind("<Button-1>", callback)
frame.pack()
root.mainloop()
Run Code Online (Sandbox Code Playgroud)
3-“跟踪”tkinter 变量类的更改,因此如果您的小部件在 textvariable 参数中使用 StringVar、BooleanVar、IntVar 或 DoubleVar,则一旦更新,您将收到回调。http://web.archive.org/web/20190712094613/https://effbot.org/tkinterbook/variable.htm
import tkinter as tk
from tkinter import messagebox as tk_messagebox
if __name__ == "__main__":
master = tk.Tk()
widget_contents = tk.StringVar()
widget_contents.set('')
some_entry = tk.Entry(master,textvariable=widget_contents,width=10)
some_entry.pack()
def entry1_callback(*args):
tk_messagebox.showinfo("entry callback", "You changed the entry %s" % str(args))
some_entry.update_idletasks()
widget_contents.trace('w',entry1_callback)
tk.mainloop()
Run Code Online (Sandbox Code Playgroud)
到目前为止,我还没有在 Tkinter 中遇到任何相当于 onChange 的东西。小部件可以绑定到各种事件,我已经明确地做到了这一点。
| 归档时间: |
|
| 查看次数: |
18881 次 |
| 最近记录: |