如何高效地在tkinter Frame中添加大量按钮?

6 投票
2 回答
3791 浏览
提问于 2025-04-17 00:02

我想在Tkinter中添加10个按钮,名字从“一”到“十”。我基本上是用一种比较简单的方法,逐个添加按钮,在我应用程序的类的init函数里。这样做是有效的,但我想让代码更简洁一些,变得更高效,比如用一个数据结构来存放所有的按钮。

我在考虑用一个buttonBox来放所有的按钮,但我不太确定能不能通过grid()来调整按钮的位置,按照我想要的方式放置。

self.one = Button(frame, text="One", command=self.callback)
self.one.grid(sticky=W+E+N+S, padx=1, pady=1)

self.two = Button(frame, text="Two", command=self.callback)
self.two.grid(sticky=W+E+N+S, row=0, column=1, padx=1, pady=1)

self.three = Button(frame, text="Three", command=self.callback)
self.three.grid(sticky=W+E+N+S, row=0, column=2, padx=1, pady=1)

# ...

self.ten = Button(frame, text="Ten", command=self.callback)
self.ten.grid(sticky=W+E+N+S, row=1, column=4, padx=1, pady=1)

有没有人能告诉我一个更高效的方法,比如用数据结构来实现?

2 个回答

1

你可以把所有按钮的属性放在一个字典里,然后通过循环来创建这些按钮,下面是一个例子:

buttons = {
    'one': {'sticky': W+E+N+S, 'padx': 1, 'pady': 1},
    'two': {'sticky': W+E+N+S, 'row': 0, 'column': 1, 'padx': 1, 'pady': 1},
    'three': {'sticky': W+E+N+S, 'row': 0, 'column': 2, 'padx': 1, 'pady': 1}
}
for b in buttons:
    button = Button(frame, text=b.title(), command=self.callback)
    button.grid(**buttons[b])
    setattr(self, b, button)

这样的话,如果需要添加新的按钮也会变得很简单。

5

与其给按钮起名为 self.oneself.two 这样的名字,不如用一个列表来管理它们,比如叫 self.button,这样会更方便。

如果这些按钮的功能 不一样,那么你需要明确地把每个按钮和它对应的操作(回调函数)关联起来。比如:

name_callbacks=(('One',self.callback_one),
                ('Two',self.callback_two),
                ...,
                ('Ten',self.callback_ten))
self.button=[]
for i,(name,callback) in enumerate(name_callbacks):
    self.button.append(Button(frame, text=name, command=callback))
    row,col=divmod(i,5)
    self.button[i].grid(sticky=W+E+N+S, row=row, column=col, padx=1, pady=1)

如果这些按钮的功能都是 相似 的,那么一个操作(回调函数)就可以处理所有按钮的事件。因为回调函数本身不能接收参数,所以你可以创建一个回调工厂,通过闭包来传递参数:

def callback(self,i): # This is the callback factory. Calling it returns a function.
    def _callback():
        print(i) # i tells you which button has been pressed.
    return _callback

def __init__(self):
    names=('One','Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten')
    self.button=[]
    for i,name in enumerate(names):
        self.button.append(Button(frame, text=name, command=self.callback(i+1)))
        row,col=divmod(i,5)
        self.button[i].grid(sticky=W+E+N+S, row=row, column=col, padx=1, pady=1)

撰写回答