str AttributeError:'str'对象没有属性'set'(更新标签)

roo*_*oot 0 python tkinter

这是一个简单的数学游戏.感兴趣的功能是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)

PM *_*ing 5

您得到的是AttributeError因为您最初将字符串绑定""到全局名称labeltext,而Python字符串没有.set方法.(这没有意义,因为Python字符串是不可变的).你最终绑定的Tkinter StringVarlabeltext,和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样式指南.

可以进行各种进一步的增强.特别是,此代码不能正常处理不是有效整数的用户输入.