Reputation: 11
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
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