[英]Python Tkinter - Name is not defined
碼:
def createLetters(frame, startX, startY, width, height, spacing):
alphabet = ["A", "B", "C", "D", "E", "F", "G", "H", "I",
"J", "K", "L", "M", "N", "O", "P", "Q", "R",
"S", "T", "U", "V", "W", "X", "Y", "Z"]
def letterAction(letter):
letter.destroy()
for i in range(0, 26):
if (i >= 9 and i <= 17):
y = startY + height + 2 * spacing
x = startX + ((width + spacing) * (i - 9))
elif (i >= 17):
y = startY + 2 * height + 3 * spacing
x = (width + spacing) / 2 + startX + ((width + spacing) * (i - 18))
elif (i <= 8):
y = startY + spacing
x = startX + ((width + spacing) * i)
exec(alphabet[i] + " = Button(" + frame + ", text = '" + alphabet[i] + "', command = letterAction(" + alphabet[i] + "))")
exec(alphabet[i] + ".place(x = " + str(x) + ", y = " + str(y) + ", width = " + str(width) + ", height = " + str(height) + ")")
錯誤:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python33\lib\tkinter\__init__.py", line 1442, in __call__
return self.func(*args)
File "E:\Hangman\hangmanTk.py", line 106, in playScreen
createLetters("playFrame", 175, 250, 50, 50, 0)
File "E:\Hangman\hangmanTk.py", line 95, in createLetters
exec(alphabet[i] + " = Button(" + frame + ", text = '" + alphabet[i] + "', command = letterAction(" + alphabet[i] + "))")
File "<string>", line 1, in <module>
NameError: name 'A' is not defined
我試圖用循環創建多個tkinter按鈕。 我可以很好地創建按鈕,但似乎無法為其創建回調。 每當我嘗試時,它會告訴我未定義用於按鈕的變量。 我嘗試在定義按鈕的上方添加“ exec(“ global” + Alphabet [i])“,但這並沒有改變任何內容。
而讓此方法起作用的問題就是為什么的完美例證。
只需創建一個將名稱映射到按鈕的dict
即可:
buttons = {}
# ...
letter = alphabet[i]
buttons[letter] = Button(frame, text = letter, command = letterAction(letter))
buttons[letter].place(x = x, y = y, width = width, height = height)
如果您真的想將dict
轉儲到locals()
(或者類似地,將self.__dict__
或globals()
或…)轉儲到這,那將是微不足道的。 但是你沒有。 您唯一需要使用該變量的位置是在letterAction
函數中。 所以:
def createLetters(frame, startX, startY, width, height, spacing):
alphabet = string.ascii_uppercase
buttons = {}
def letterAction(letter):
buttons[letter].destroy()
for i, letter in enumerate(alphabet):
if (i >= 9 and i <= 17):
y = startY + height + 2 * spacing
x = startX + ((width + spacing) * (i - 9))
elif (i >= 17):
y = startY + 2 * height + 3 * spacing
x = (width + spacing) / 2 + startX + ((width + spacing) * (i - 18))
elif (i <= 8):
y = startY + spacing
x = startX + ((width + spacing) * i)
buttons[letter] = Button(frame, text = letter, command = letterAction(letter))
buttons[letter].place(x = x, y = y, width = width, height = height)
但是請注意,這做錯了事。 command = letterAction(letter)
—是直接運行還是通過exec
—現在將調用letterAction(letter)
,銷毀按鈕甚至創建它,然后返回None
,然后將其設置為command
。
您需要lambda: letterAction(letter)
或partial(letterAction, letter)
來解決此問題。
另外,無論現在還是以后,您都無法編寫將按鈕變量本身傳遞給letter
代碼,因為該變量尚不存在。 您必須像上面一樣將字母作為字符串傳遞。
但是,實際上,如果您考慮一下,則根本不需要這些按鈕變量,無論是dict
還是其他形式。 您只需要一種將每個按鈕綁定為自己的回調目標的方法,對嗎? 有很多方法可以做到這一點,但是很明顯的一個類是繼承或委托給Button
(或者,在這種情況下,兩者都不是,因為您不需要將其用作按鈕,甚至不必記住它) ,創建后)。
在此過程中,讓我們刪除一些無關緊要的內容,以免使情況變得更難以閱讀並解決17
似乎屬於兩個不同組的問題……
class SelfDestructiveButton(object):
def __init__(self, frame, letter, x, y, width, height):
self.button = Button(frame, text=letter, command=self.command)
self.button.place(x=x, y=y, width=width, height=height)
def command(self):
self.button.destroy()
def createLetters(frame, startX, startY, width, height, spacing):
for i, letter in enumerate(string.ascii_uppercase):
if 9 <= i <= 17:
y = startY + height + 2 * spacing
x = startX + ((width + spacing) * (i - 9))
elif i > 17:
y = startY + 2 * height + 3 * spacing
x = (width + spacing) / 2 + startX + ((width + spacing) * (i - 18))
else:
y = startY + spacing
x = startX + ((width + spacing) * i)
SelfDestructiveButton(frame, letter, x, y, width, height)
if 'J' <= letter <= 'R'
甚至可能更清楚,因為它是字母,而不是調試時要看到的數字。
首次調用exec
該字符串的計算結果為:
"A = Button(<frame>, text = 'A', command = letterAction(A))"
因此,在定義A
(名稱)之前,您要先對其進行引用。 我猜你忘了第二個alphabet[i]
的單引號:
exec(alphabet[i] + " = Button(" + frame + ", text = '" + alphabet[i] + "', command = letterAction('" + alphabet[i] + "'))")
注意,這將調用letterAction('A')
,即'A'.destroy()
,由於字符串沒有destroy()
方法,該方法將引發AttributeError
。 letterAction
應該實現什么?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.