问题
I would like to make some buttons, with a list of items I get back from a database, that all call a function passing in the list item. Something like this code but that works. The problem with this code is that all of the buttons call the function with 'item3'
.
#!/usr/bin/env python
from Tkinter import *
root = Tk()
def func(name):
print name
mylist = ['item1','item2','item3']
for item in mylist:
button = Button(root,text=item,command=lambda:func(item))
button.pack()
root.mainloop()
回答1:
There are two things here:
You need to indent the following line one level:
button.pack()
Currently, you only have the
pack
method being called on the last button. Making this change will cause it to be called for each button.All of the buttons are sending
'item3'
tofunc
because that is the current value ofitem
. It is important to remember that the expression enclosed by a lambda function is evaluated at run-time, not compile-time.However, it is also important to remember that both a function's parameters as well as their default values (if any) are evaluated at compile-time, not run-time.
This means that you can fix the problem by giving the lambda a parameter whose default value is set to
item
. Doing so will "capture" the value ofitem
for each iteration of the for-loop.
Below is a version of your script that addresses these issues:
from Tkinter import *
root = Tk()
def func(name):
print name
mylist = ['item1', 'item2', 'item3']
for item in mylist:
button = Button(root, text=item, command=lambda x=item: func(x))
button.pack()
root.mainloop()
回答2:
You should use functools.partial:
import functools
from Tkinter import *
root = Tk()
def func(name):
print name
mylist = ['item1','item2','item3']
for item in mylist:
button = Button(root,text=item,command=functools.partial(func,item))
button.pack()
root.mainloop()
回答3:
The same logic, but this is an example of creating a calculator. Only display, no calculations. Here I used grid() instead of pack().
import tkinter
main_window = tkinter.Tk()
main_window.title("Calculator")
main_window.geometry('500x500+550+200')
main_window['padx'] = 8
main_window.columnconfigure(0, weight=1)
main_window.columnconfigure(1, weight=1)
main_window.columnconfigure(2, weight=1)
main_window.columnconfigure(3, weight=1)
main_window.columnconfigure(4, weight=1)
main_window.columnconfigure(5, weight=1)
main_window.rowconfigure(0, weight=1)
main_window.rowconfigure(1, weight=1)
main_window.rowconfigure(2, weight=1)
main_window.rowconfigure(3, weight=1)
main_window.rowconfigure(4, weight=1)
main_window.rowconfigure(5, weight=1)
main_window.rowconfigure(6, weight=1)
main_window.rowconfigure(7, weight=1)
title_label = tkinter.Label(main_window, text="Calculator")
title_label.grid(row=0, columnspan=6)
number_entry = tkinter.Entry(main_window)
number_entry.grid(row=1, columnspan=4, sticky='nwes')
button_list = [('C', 'E'),
('7', '8', '9', '+'),
('4', '5', '6', '-'),
('1', '2', '3', '*'),
('0', '=', '/')]
for outer_num, outer_val in enumerate(button_list):
for inner_num, inner_val in enumerate(outer_val):
x = 1
y = inner_num
if inner_val == "=":
x = 2
if inner_val == "/":
y += 1
tkinter.Button(main_window, text=inner_val).grid(row=outer_num + 2, column=y, columnspan=x,
sticky='news')
main_window.mainloop()
来源:https://stackoverflow.com/questions/21738149/make-tkinter-buttons-for-every-item-in-a-list