user1727585
user1727585

Reputation: 11

Label does not update on button click

We have to make a test for elementary school kids to test there skills in math. I need the label on the left to have a random equation, and the right have an entry form, and the far right to have a button that checks if the answer they gave is correct. If they got it right a new equation is given.

from tkinter import Label, Frame, Entry, Button, LEFT, RIGHT, END, TOP, END
from tkinter.messagebox import showinfo
from random import randrange

class Ed(Frame):
    'Simple arithmetic education app'
    def __init__(self,parent=None):
        'constructor'
        Frame.__init__(self, parent)
        self.pack()
        Ed.new_problem(self)
        Ed.make_widgets(self)
        self.tries = 0

    def make_widgets(self):
        'defines Ed widgets'
        if self.plusminus == 1: 
            Label(self, text=(self.a ,"+" ,self.b)).pack(side=LEFT)
        else:
            Label(self, text=(self.a, "-" ,self.b)).pack(side=LEFT)       
        self.ent = Entry(self)
        self.ent.pack(side=LEFT)        
        Button(self, text='Enter', command=self.evaluate).pack(side=RIGHT)

    def new_problem(self):
        'creates new arithmetic problem'
        self.a = randrange(1,10,1)
        self.b = randrange(1,10,1)
        self.c = randrange(1,10,1)
        if self.c < 5:
            self.total = self.a + self.b
            self.plusminus = 1     #plusminus = plus
        else:
            self.total = self.a - self.b
            self.plusminus = 0     #plusminus = minus

    def evaluate(self):
        'handles button "Enter" clicks by comparing answer in entry to correct result'
        if self.total == eval(self.ent.get()):
            showinfo(title='YAY', message='You are CORRECT!')
            self.ent.delete(0,END)
        else:
            self.ent.delete(0,END)
            self.ent.insert(END, 'Wrong. Try again.')
            self.tries+=1


Ed().mainloop()

The problem is the equation does not update when the answer is correct. So when I enter 12 when the question is 8 + 4. It cays correct but keeps 8 + 4 tho I want it to change to a new equation.

Upvotes: 0

Views: 491

Answers (1)

Matthew Trevor
Matthew Trevor

Reputation: 14961

You're only calling new_problem when your Ed object is instantiated. It's never called again afterwards, and doing so won't actually change the existing set up, as you only create the labels for your widget once, also at instantiation.

What you need to do is pass in a tkinter.StringVar to your Label widget, and then set the arithmetic problem on that variable. You then run new_problem after each successful answer.

I've updated your code slightly to use super and run methods directly on the instance rather than via the class, but this should work:

from tkinter import Label, Frame, Entry, Button, LEFT, RIGHT, END, TOP, END, StringVar
from tkinter.messagebox import showinfo
from random import randrange

class Ed(Frame):
    """Simple arithmetic education app"""
    def __init__(self,parent=None):
        """constructor"""
        super().__init__(parent)
        self.tries = 0
        self.problem = StringVar()
        self.make_widgets()
        self.new_problem()
        self.pack()

    def make_widgets(self):
        """defines Ed widgets"""
        self.label = Label(self, textvariable=self.problem)
        self.label.pack(side=LEFT)
        self.ent = Entry(self)
        self.ent.pack(side=LEFT)
        Button(self, text='Enter', command=self.evaluate).pack(side=RIGHT)

    def new_problem(self):
        """creates new arithmetic problem"""
        self.tries = 0
        self.a = randrange(1,10,1)
        self.b = randrange(1,10,1)
        if randrange(1,10,1) < 5:
            self.total = self.a + self.b
            self.plusminus = '+'
        else:
            self.total = self.a - self.b
            self.plusminus = '-'
        self.problem.set( (self.a , self.plusminus, self.b) )

    def evaluate(self):
        """handles button "Enter" clicks by comparing answer in entry to correct result"""
        if self.total == int(self.ent.get()):
            showinfo(title='YAY', message='You are CORRECT!')
            self.ent.delete(0,END)
            self.new_problem()
        else:
            self.ent.delete(0,END)
            self.ent.insert(END, 'Wrong. Try again.')
            self.tries += 1

Ed().mainloop()

I've also changed your eval to an int...you really don't want to be doing that, because it enables users to inject python code into your application.

For example, I can type the following as my "answer":

showinfo(title="Blah", message="Look ma - No hands!")

That would just bring up a simple message box, but the door is wide open for more involved mischief.

Upvotes: 1

Related Questions