我对以下代码的问题是通过lambda传递'i'(只是一个简单的数字范围但是根据number_box更改)以回调,以便创建每个框的单独功能。
我已经尝试过阅读教程并在我的代码中尝试了各种各样的东西,但它要么不起作用,要么我得到错误'lambda()只需要2个参数,3给出'等等。我相信我需要做'我'列表,但我仍然得到这个特殊的错误..
我已经对出现问题的代码发表了评论。我需要返回每个框内的值以及覆盖文本。
谢谢。
self.clicked = [] # In my __init__ definition
self.numbers = [StringVar() for i in xrange(self.number_boxes) ] # Create Stringvar for each box
for i in xrange(self.number_boxes): # For each number, create a box
self.clicked.append(False) # Not clicked in yet
self.box.append(Entry(self.frame_table,bg='white',borderwidth=0, width=10, justify="center", textvariable=self.numbers[i], fg='grey')) # Textvariable where I enter a value to get after, need to do for each box (use box[i] but cannot for append)
self.box[i].grid(row=row_list,column=column+i, sticky='nsew', padx=1, pady=1)
self.box[i].insert(0, "Value %g" % float(i+1))
self.box[i].bind("<Button-1>", lambda event, index=i : self.callback(event, index)) # Need to pass the 'i's' to callback but having lambda difficulties
for i in self.numbers:
i.trace('w',lambda index=i: self.numberwritten(index) ) # Need for each box again here
def numberwritten(self, index): # A way of combining numberwritten and callback?
po = self.box[index].get() # Get the values in each box
print po
def callback(self, event, index):
if (self.clicked[index] == False): # When clicked in box, overwrite default text with value and change colour to black, not grey
self.box[index].delete(0, END)
self.box[index].config(fg='black')
self.clicked[index] = True
更新:当前问题:需要将'i'的所有值传递给回调而不仅仅是一个但是如何将列表放入lambda?
错误:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python26\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
TypeError: lambda() takes at most 1 argument (3 given)
答案 0 :(得分:2)
您的代码非常接近,不过这一行:
self.box[i].bind("<Button-1>", lambda self, event,i : self.callback(event, data))
应该是
self.box[i].bind("<Button-1>", lambda event, index=i: self.callback(event, index))
对象index
只是我们为其分配值i
的任意标签。请注意,如果我们传递i
而不是变量名,Python会抛出错误。我们不需要通过self
;它通过函数调用中的使用隐式传递:self.callback()
。
我唯一的另一个评论是你应该将clicked
变成一个列表,以便你可以跟踪用户选择的对象。您可以按box
形成的方式完全形成。祝你好运。
以下是将clicked
转换为列表的一些提示,因为我认为这是您目前遇到的问题。 编辑:根据J.F. Sebastian的评论改变了几行。
# Create an empty list based on the number of boxes created
# above. This could go in your class's __init__ function,
# or it could be declared globally, depending on the scope
# of self.box and the loop which determines its length.
self.clicked = ([False] * len(self.box))
# Finally, in your callback, check one member of the list,
# depending on which box was clicked.
def cb(self, event, index):
if not self.clicked[index]:
self.box[index].delete(0, END)
self.box[index].config(fg='black')
self.clicked[index] = True
# Print the value of each of the widgets stored in the box list.
for i, j in enumerate(self.box):
print("%ith element: %s" % (i, j.get()))
答案 1 :(得分:0)
<强>更新强>: 看来你的lambda完全超级丰富。完全删除它。
尝试:
self.box[i].bind("<Button-1>",self.callback)
而不是:
lambda self, event, i: self.callback(event, i)
更新
当我输入我的答案时,你似乎可能会使情况恶化 对lambda-idiom的一点澄清可以帮助你解决问题 以上。 ; - )
lambda函数也称为匿名函数,因为它们不需要 有一个名字。
比较以下示例:
>>>ulist = 'a1 s3 d2 f4 k6 w9'.split()
def normal_sort(L,R):
result = int(L[1]) - int(R[1])
return result
>>> sorted(ulist, normal_sort)
['a1', 'd2', 's3', 'f4', 'k6', 'w9']
与lambda函数相同:
sorted(ulist, lambda L, R: int(L[1])-int(R[1]))
['a1', 'd2', 's3', 'f4', 'k6', 'w9']
lambda函数有
您可以通过将lambda函数指定给名称来命名它:
lambda_sort = lambda L, R: int(L[1])-int(R[1])
但是切换到正常功能可能已经很有用了。