这是一个简单的数学游戏.感兴趣的功能是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()
Run Code Online (Sandbox Code Playgroud)
您得到的是AttributeError因为您最初将字符串绑定""到全局名称labeltext,而Python字符串没有.set方法.(这没有意义,因为Python字符串是不可变的).你最终绑定的Tkinter StringVar来labeltext,和StringVar小号做有一个.set方法,但你的代码做它的后已试图打电话.set对普通的Python字符串.
IntVar您命名时会出现类似的问题userAnswer.这还有一个问题:它的名字与你的一个功能发生冲突.你做不到!
这是修复后的代码版本,还有一些其他的小改动.没有必要global在那些StringVars 上使用指令,或者IntVar因为你只是调用那些对象的方法.只有global在需要对全局对象执行赋值时才需要,只需访问全局的现有值或调用其中一个方法就不需要该global指令.
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()
Run Code Online (Sandbox Code Playgroud)
但是,该代码仍有几个问题.它只能问一个问题.每次点击"提交"按钮,它都会添加一个新的Label小部件,我认为你并不想要它.
使用全局变量不是一个好主意.它们破坏了模块化,使代码更难理解,更难以修改和重用.
这是程序的增强版本,它将所有内容放入一个类中,因此我们可以使用实例属性而不是全局变量.
这个版本提出了多个问题.它没有"提交"按钮,而是当用户点击主键盘或数字键盘上的Enter/Return键时,问题会自动提交.
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()
Run Code Online (Sandbox Code Playgroud)
请注意import tkinter as tk声明.这是很多更好地使用这种形式比from tkinter import *自认为"明星"进口转储130名进入你的空间,它是凌乱的,并可能导致名称冲突,特别是如果你做明星的进口与其它模块.该import tkinter as tk表单要求您进行更多的输入,但它也使代码更容易阅读,因为很明显哪些名称来自Tkinter.
我还更改了变量的名称和类方法(函数),因此它们符合Python PEP-0008样式指南.
可以进行各种进一步的增强.特别是,此代码不能正常处理不是有效整数的用户输入.