0

问题

我正在创建一个应用程序来处理一个人的所有联系方式。记录存储在文本文件中,因此第 5 到第 10 索引由用户给出的每个联系人的昵称组成。我想将所有这些昵称作为按钮列出,当用户选择任何一个按钮时,该联系人的详细信息将使用tkSimpleDialog.showinfo('text','contact details').


目标

  1. 决定在按钮列表中单击了哪个按钮。
  2. 这是我经常面临的一个问题:将参数传递给回调函数


代码

请注意,此代码没有完成我想要实现的功能。

buttons = []

inFile = open('test','r')

for i in inFile:

    thisrecord = i    
    buttons.append(Button(self.frame,text='Name: %s' %i[5:10],command=self.show(thisrecord))

inFile.close()


我试过的

当我尝试上面的代码时,发生的事情是每次都显示存储在文件中的最后一条记录,无论我按下什么按钮。我发现了为什么会发生这种情况。显然,按钮都是一次创建的,然后每当调用每个按钮时都会调用回调函数。

如果我的按钮数量有限,那么我绝对可以为每个按钮定义函数,然后将它们用作回调。这就是我在我的应用程序的欢迎页面中所做的事情,该页面具有以下按钮:add new contact等等see details of contact

但是在这种情况下,记录的数量不是固定的。所以我在这里修复,不明白该怎么做。

我进一步尝试使用检查按钮,以便用户想要查看的任何记录,他都可以勾选并按继续并继续。但即使这样也失败了,因为首先创建了检查按钮,而不是在代码运行时。

帮我解决这个问题。


眼镜

Linux Mint 14
Python 2.7
tkinter 8.5

4

3 回答 3

3

正如您已经注意到的,您self.show(thisrecord)甚至可以在创建按钮之前调用,因为这是按钮参数的一部分。您希望将函数用作回调。

因此,要修复它,请创建一个返回可用作回调的函数的函数:

# add to your class
def showCallback(self,record):
    """ returns a callback for self.show """
    def callback():                 # make a new function
        return self.show(record)    # that shows the given record
    return callback                 # return this function

for thisrecord in inFile:
    buttons.append(Button(self.frame,text='Name: %s' %i[5:10],
                           command=self.showCallback(thisrecord))

self.showCallback(thisrecord)现在将为每条记录返回不同的函数。

于 2013-04-16T09:06:36.050 回答
3

在您的示例self.show(thisrecord)中,在创建 Button 时执行,结果(可能为 None)绑定到command.

您想要的是在此处传递一个函数,该函数在您单击按钮时执行,而不是在构建时执行。一种方法是使用functools.partial,如下所示:

import Tkinter as tk
from functools import partial

root = tk.Tk()
buttons = []
inFile = ['... line1 ...', '... line2 ...', '...']

def show(par):
    print par

for i in inFile:
    thisrecord = i    
    button = tk.Button(root, text='Name: %s' %i[5:10], command=partial(show, thisrecord))
    button.pack()
    buttons.append(button)

tk.mainloop()

或者你可以定义你自己的函数,它返回一个回调函数来完成这项工作。

注意:发布示例时,最好包含将其粘贴到解释器中以使其运行所需的所有内容...

于 2013-04-16T09:06:44.797 回答
1

你在做什么:command=self.show(thisrecord)你实际上是在执行self.show(..)带有参数的函数thisrecord并将返回值分配给 key command

你实际上应该做什么:

command=partial(self.show, thisrecord)

所做partial的是返回一个带有冻结部分参数的新函数。


另一个例子来演示partial

from functools import partial

def fn(x):
    print x

functions = []
for i in range(0,3):
    functions.append(partial(fn, i))

for func in functions:
    func()
于 2013-04-16T09:07:34.350 回答