954,549 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Tkinter Help

Hi there,

My niece often asks me to quiz her on her times tables, so I thought I'd spare myself any further effort and write a program to ask her random multiplication questions. I used Tkinter to create a GUI with a label asking the question, an entry box for her to input answers, and a button to ask the next question. I want to bind the Enter key to submit answers, but I can't figure out how to send the date to my Ask method. Any ideas?

Thanks,
Jay

Jayzilla
Newbie Poster
5 posts since Jul 2006
Reputation Points: 10
Solved Threads: 0
 

Please show your code. It makes it tough to help without it. Others too can learn from your code and the answers.

This would be one way to bind Entry box enter1 to return key:

enter1.bind('<Return>', func=my_function)

The data is then in enter1.get() as a string.

bumsfeld
Nearly a Posting Virtuoso
1,445 posts since Jul 2005
Reputation Points: 404
Solved Threads: 184
 

I managed to fix it. Not sure how :D

from Tkinter import *
import tkMessageBox
import random
import string

def ask():
    global num1 
    num1 = random.randint(1, 12)
    global num2 
    num2 = random.randint(1, 12)
    global answer 
    answer = num1 * num2
    label1.config(text='What is ' + str(num1) + 'x' + str(num2) + '?')
    
def checkAnswer():
    herAnswer = entry1.get()
    if int(herAnswer) != answer:
        tkMessageBox.showwarning(message='The answer is: ' + str(answer))
    else:
        tkMessageBox.showinfo(message='Correct!')

#set the window
root = Tk()
root.title("Helena's Multiplication Quiz")
root.geometry('500x500')

#add label
label1 = Label(root)
label1.grid(row=2, column=0)

#add entry
entry1 = Entry(root)
entry1.grid(row=3, column=0)


#add button
askBtn = Button(root, text='Ask Me a Question!', command=ask)
askBtn.grid(row=4, column=0)

okButton = Button(root, text='OK', command=checkAnswer)
okButton.grid(row=4, column=1)

tkMessageBox.showinfo(message="Hi, Helena!  Let's do some multiplication problems!")
root.mainloop()
Jayzilla
Newbie Poster
5 posts since Jul 2006
Reputation Points: 10
Solved Threads: 0
 

Looks like a nice program. On my computer (OS = Windows XP) the last tkMessageBox.showinfo() prevents any focus on entry1, no cursor! Strange indeed!

vegaseat
DaniWeb's Hypocrite
Moderator
5,989 posts since Oct 2004
Reputation Points: 1,345
Solved Threads: 1,417
 
Looks like a nice program. On my computer (OS = Windows XP) the last tkMessageBox.showinfo() prevents any focus on entry1, no cursor! Strange indeed!


very nice indeed, but i have the same issue, (running windows xp) except it does it to me straight away.

a1eio
Junior Poster
141 posts since Aug 2005
Reputation Points: 26
Solved Threads: 25
 

That's very odd. o_0. Works just fine on my OS (Linux) but I'll try it on a Windows machine when I have a little time. Thanks for listening to me ramble :D

Jayzilla
Newbie Poster
5 posts since Jul 2006
Reputation Points: 10
Solved Threads: 0
 

Helena is lucky to have her own programmer! I too had Windows problem and solved it by putting message in label. I couldn't help myself, just had to add some colour. I hope Helena is not colorblind. I also show you how to bind the return key. Here is your program with some colour:

from Tkinter import *
import tkMessageBox
import random
#import string  # not needed!

def ask():
    global num1 
    num1 = random.randint(1, 12)
    global num2 
    num2 = random.randint(1, 12)
    global answer 
    answer = num1 * num2
    label1.config(text='What is ' + str(num1) + 'x' + str(num2) + '?')
    # put the cursor into the Enter-Box
    entry1.focus_set()
    
def checkAnswer():
    herAnswer = entry1.get()
    # if empty give message
    if len(herAnswer) == 0:
        tkMessageBox.showwarning(message='Need to enter some number!')
        return
    if int(herAnswer) != answer:
        tkMessageBox.showwarning(message='The answer is: ' + str(answer))
    else:
        tkMessageBox.showinfo(message='Correct!')

#set the window
root = Tk()
# add some color
root.tk_bisque()
root.title("Helena's Multiplication Quiz")
root.geometry('500x500')

# replaces tkMessageBox.showinfo() 
label2 = Label(root, text="Hi, Helena!\n  Let's do some multiplication problems!")
# add a colorful font
label2.config(font=('times', 18, 'bold'), fg='red', bg='yellow')
label2.grid(row=0, column=0)

#add label
label1 = Label(root)
label1.grid(row=2, column=0)

#add entry
entry1 = Entry(root)
entry1.grid(row=3, column=0)
# bind the return key
entry1.bind('<Return>', func=lambda e:checkAnswer())

#add button
askBtn = Button(root, text='Ask Me a Question!', bg='green', command=ask)
askBtn.grid(row=4, column=0)

okButton = Button(root, text='OK', command=checkAnswer)
okButton.grid(row=4, column=1)

# seems to create a problem with the entry1 focus in Windows, replace with label2
#tkMessageBox.showinfo(message="Hi, Helena!  Let's do some multiplication problems!")

root.mainloop()
bumsfeld
Nearly a Posting Virtuoso
1,445 posts since Jul 2005
Reputation Points: 404
Solved Threads: 184
 

Thanks very much, bumsfeld. Now I've learned a few things! :D I'm now reading about lambda functions, and having a hard time with it, but hopefully I'll fully understand with a bit more reading.

My youngest niece (Susan) was very jealous, so I had to modify Helena's script to display addition problems. Oh boy..these kids are spoiled! :D

Jayzilla
Newbie Poster
5 posts since Jul 2006
Reputation Points: 10
Solved Threads: 0
 

I guess the Tkinter GUI looks a lot nicer on Linux or Unix computers.

On Windows computers it does not take advantage of the native windows design, and the Tkinter widgets appear downright gawky. This might be the reason the wxPython GUI is preferred by Windows users.

In GUI programs, you deal a lot with callback functions and events. There lambda allows you to handle arguments more gracefully.

vegaseat
DaniWeb's Hypocrite
Moderator
5,989 posts since Oct 2004
Reputation Points: 1,345
Solved Threads: 1,417
 

OK, why did you have

entry1.bind('<Return>', func=lambda e:checkAnswer())

instead of entry1.bind('<Return>', func=checkAnswer) ?

Thanks,
Jeff Cagle

jrcagle
Practically a Master Poster
608 posts since Jul 2006
Reputation Points: 92
Solved Threads: 156
 

Answered my own question. The event passes an event object to the handler. That's the "e" argument in the lambda function. If the handler is not expecting an event object to be passed, *crash*. Thus, it's efficient to use a lambda to "catch" the event and ignore it, calling your handler without passing the event.

Sorry for the dumb question.

jrcagle
Practically a Master Poster
608 posts since Jul 2006
Reputation Points: 92
Solved Threads: 156
 

This was not a dumb question! It was a question that needed to be asked! So, thanks for asking it and answering it!

bumsfeld
Nearly a Posting Virtuoso
1,445 posts since Jul 2005
Reputation Points: 404
Solved Threads: 184
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You