我使用for循环在gui窗口中添加了多个spinbox和标签。 for循环在同一行上创建spinbox和label。然后在循环的下一个刺激中创建另一行标签和旋转框。如何从旋转框中获取值(单击时或增加或减少时),然后使用单击的旋转框中的值进行计算并更新与旋转框位于同一行的标签?
我添加了用于使用for循环创建旋转框的代码。
import Tkinter as tk
win = tk.Tk()
val = int()
def exitProgram():
print("Exit Button pressed")
win.quit()
win.destroy()
def createSpinBoxes():
boxes = []
lbls = []
corr = []
def Correction(event):
print "you clicked on", event.widget
w = event.widget
if isinstance(w, tk.Spinbox):
print "what is w??"
print w
print repr(w)
data = float(w.get())
data = (data/2)+3
print data
lbl.configure(text = str(data))
def TestCorr(data):
print data
# Create Spinbox Title label
lbl = tk.Label(win, text = 'SpBox#',
background = "light gray",
font = ('Courier' , 10))
lbl.grid(column = 0, row = 0, sticky = 'we')
# Create Nominal Value Title label
lbl = tk.Label(win, text = 'Nom Val',
background = "light gray",
font = ('Courier' , 10))
lbl.grid(column = 1, row = 0, sticky = 'w')
# Create Correction Title label
lbl = tk.Label(win, text = 'Corr',
background = "light gray",
font = ('Courier' , 10))
lbl.grid(column = 2, row = 0, sticky = 'we')
# Create Value Parameter labels
valLabels = ['IN VAL ',
'OUT VAL',
'COR VAL']
# Nominal values
valNom = [37.0, # Value 1
64.0, # Value 2
20.0] # Value 3
# Nominal value Level Range
valRange = [33, # Min Value 1
44, # Max Value 1
62, # Min Value 2
68, # Max Value 2
15, # Min Value 3
25] # Max Value 3
valRngCnt = 0
for i in range(0, 3):
lbl = tk.Label(win,
text = valLabels[i],
font = ('Courier' , 10),
background = "light pink").grid(column = 0, row = i+2, sticky = 'w')
val = valNom[i]
SPbox = tk.Spinbox(win,
from_= valRange[valRngCnt],
to = valRange[valRngCnt+1],
font = ('Courier' , 10),
width = 5,
increment=0.1,
textvariable=val,
command=lambda: TestCorr(val))
SPbox.grid(column = 1, row = i+2, sticky = 'w')
SPbox.delete(0,"end")
SPbox.insert(0,valNom[i])
# Debug lines
print str(valNom[i]) + " Start Range: " + str(valRange[valRngCnt]) + " End Range: " + str(valRange[valRngCnt+1])
print valRngCnt
valRngCnt += 2
lbl = tk.Label(win,
background = "light pink",
font = ('Courier' , 10))
lbl.grid(column = 2, row = i+2, sticky = 'w')
boxes.append(SPbox)
lbls.append(lbl)
corr.append(corr)
SPbox.bind("<Button-1>", Correction)
# Debug line
print boxes
createSpinBoxes()
exitButton = tk.Button(win,
text = "Exit",
background = "YELLOW",
command = exitProgram)
exitButton.grid(column = 4, row = 7, sticky = 'e')
tk.mainloop()
答案 0 :(得分:0)
在Correction
当你这样做时:
lbl.configure(text = str(data))
您希望lbl
与点击旋转框相关联的正确吗?相反,它会在lbl
循环之后使用分配给Correction
变量的小部件for
被称为,因此它只会更新最后lbl
。
有两种方法可以确保Correction
更新正确的标签:
Correction
首先,这意味着Correction
需要将标签更新为参数:
def Correction(event, label):
...
#instead of lbl you use label
label.configure(text=str(data))
您可以使用functools.partial
制作回调包装器:
wrapper = functools.partial(Correction, label=lbl) #current lbl is saved with the wrapper
SPbox.bind("<Button-1>", wrapper)
#the two above would replace this line:
#SPbox.bind("<Button-1>", Correction)
我个人更喜欢这种方法,你可以在所有tk小部件上创建任意属性:
SPbox.label = lbl #make the label an attribute of each SPbox.
#this would be done around the same time as you do the binding:
SPbox.bind("<Button-1>", Correction)
然后lbl
代替Correction
,您会更新w.label
:
#instead of lbl.configure(text = str(data))
w.label.configure(text = str(data))
请注意,您可能希望完全使用<Button-1>
逐步淘汰,因为正如您所遇到的那样,它在点击箭头时并不总是触发,并且在使用箭头键时它肯定不会触发,一个解决方案是在初始化之后更改Spinbox的command
,以便它触发虚拟事件(这样您仍然可以在编写时使用Correction
)然后绑定该虚拟事件而不是{{ 1}}:
<Button-1>
然后只需将绑定更改为使用SPbox = tk.Spinbox(win,
...,
textvariable=val)#,
#command=lambda: TestCorr(val)) #we can't make a partial that references SPbox because it doesn't exist yet!
SPbox["command"] = partial(SPbox.event_generate, "<<Change>>")
SPbox.grid(column = 1, row = i+2, sticky = 'w')
...
,它就会在每次更改时生成并处理该事件...
<<Change>>