这是一款简单的数学游戏。感兴趣的功能是checkAnswer()
。我正在尝试更新label1
,以便标签使用新的str更新,而不是连续打印多个标签。
错误:
AttributeError:'str'对象没有属性'set'
from tkinter import *
from random import randint
num1 = 0
num2 = 0
userAnswer = 0
answer = 0
score = 0
labeltext = ""
#PROGRAM FUNCTIONS
def question():
global num1, num2
global answer
num1 = randint(1,10)
num2 = randint(1,10)
question = Label(text = "What is " + str(num1)+ " + " + str(num2) + "?").pack()
answer = num1+num2
print(answer) #testing purposes
def userAnswer():
global userAnswer
userAnswer = IntVar()
entry = Entry(root, textvariable = userAnswer).pack()
submit = Button(root, text = "submit", command = checkAnswer).pack()
def checkAnswer():
global labeltext
print(userAnswer.get())
if userAnswer == answer:
labeltext.set("good job")
score += 1
elif userAnswer != answer:
labeltext.set("oh no")
labeltext = StringVar()
label1 = Label(root, textvariable = labeltext).pack()
#INTERFACE CODE
root = Tk()
question()
userAnswer()
root.mainloop()
答案 0 :(得分:5)
您得到的是AttributeError
,因为您最初将字符串""
绑定到全局名称labeltext
,而Python字符串没有.set
方法。 (这不会有意义,因为Python字符串是不可变的)。您最终将Tkinter StringVar
绑定到labeltext
,而StringVar
做有.set
方法,但您的代码在此之后执行此操作&#39 ; s已经尝试在普通Python字符串上调用.set
。
您命名为IntVar
的{{1}}也会出现类似问题。这还有一个问题:它的名字与你的一个功能发生冲突。你做不到!
这是您修改过的代码版本,还有一些其他的小改动。由于您只是调用这些对象的方法,因此无需在userAnswer
或global
上使用StringVar
指令。如果需要对全局对象执行赋值,只需访问全局的现有值或调用其中一个方法,则只需要IntVar
1}}。
global
但是,该代码仍有几个问题。它只能问一个问题。每次你点击"提交"按钮它会添加一个新的global
小部件,我认为你真的不想这样做。
使用全局变量不是一个好主意。它们打破了模块化,这使得代码更难理解,更难以修改和重用。
这是程序的增强版本,它将所有内容放入一个类中,因此我们可以使用实例属性而不是全局变量。
此版本提出了多个问题。它没有"提交"按钮,而当用户点击主键盘或数字键盘上的Enter / Return键时,问题会自动提交。
from tkinter import *
from random import randint
#PROGRAM FUNCTIONS
def question():
global true_answer
num1 = randint(1,10)
num2 = randint(1,10)
Label(text="What is " + str(num1)+ " + " + str(num2) + "?").pack()
true_answer = num1 + num2
print(true_answer) #testing purposes
def answer():
Entry(root, textvariable=userAnswer).pack()
Button(root, text="submit", command=checkAnswer).pack()
def checkAnswer():
global score
print(userAnswer.get()) #testing purposes
if userAnswer.get() == true_answer:
labeltext.set("good job")
score += 1
else:
labeltext.set("oh no")
label1 = Label(root, textvariable=labeltext).pack()
#INTERFACE CODE
root = Tk()
true_answer = 0
score = 0
userAnswer = IntVar()
labeltext = StringVar()
question()
answer()
root.mainloop()
请注意Label
声明。使用此表单比使用import tkinter as tk
from random import randint
class Quiz(object):
def __init__(self):
root = tk.Tk()
# The question
self.question_var = tk.StringVar()
tk.Label(root, textvariable=self.question_var).pack()
# The answer
self.user_answer_var = tk.StringVar()
entry = tk.Entry(root, textvariable=self.user_answer_var)
entry.pack()
# Check the answer when the user hits the Enter key,
# either on the main keyboard or the numeric KeyPad
entry.bind("<Return>", self.check_answer)
entry.bind("<KP_Enter>", self.check_answer)
self.true_answer = None
# The response
self.response_var = tk.StringVar()
self.score = 0
tk.Label(root, textvariable=self.response_var).pack()
# Ask the first question
self.ask_question()
root.mainloop()
def ask_question(self):
num1 = randint(1, 10)
num2 = randint(1, 10)
self.question_var.set("What is {} + {}?".format(num1, num2))
self.true_answer = num1 + num2
#print(self.true_answer) #testing purposes
def check_answer(self, event):
user_answer = self.user_answer_var.get()
#print(user_answer) #testing purposes
if int(user_answer) == self.true_answer:
text = "Good job"
self.score += 1
else:
text = "Oh no"
self.response_var.set('{} Score={}'.format(text, self.score))
# Clear the old answer and ask the next question
self.user_answer_var.set('')
self.ask_question()
Quiz()
更好 更好 import将130个名称转储到您的命名空间中,这很糟糕,并且可能导致名称冲突,尤其是如果您使用其他模块进行星型导入。 import tkinter as tk
表单要求您进行更多的输入,但它也使代码更容易阅读,因为很明显哪些名称来自Tkinter。
我还更改了变量和类方法(函数)的名称,因此它们符合Python PEP-0008样式指南。
可以进行各种进一步的改进。特别是,此代码不能优雅地处理不是有效整数的用户输入。