python tkinter "in" operator doesn't work - python

my problem is the programme won't state the answer as correct only if you put the answer alone, but i want to make that you can actually put a phrase in the entry widget and if the answer is in that phrase it would say correct, i made this work without tkinter but i canno't make it work in tkinter here is my code, could you please help, thanks.
the code
import tkinter as tk
from time import sleep
win = tk.Tk()
win.title("Learning game")
class Question:
def __init__(self,prompt,answer):
self.answer = answer
self.prompt = prompt
score = 0
def ask():
global questions
global useranwser
global score
if questions:
#Check both the possible answers
if useranwser.get() in questions[0].answer:
print("Correct")
score += 1
else:
print("Incorrect")
questions.pop(0)
if questions:
s.set(questions[0].prompt)
else:
print('Done')
print("Your score is : ",score)
quit() #optional
useranwser.set('')
question_prompts = [
"When did Tunisia gain independence? \n 1956 , 1984 , 1965 \n", "What is the captial of tunis ? \n Tunis, Gafsa, Nabuel \n",
"Who won 2018 football world cup ? \n Italy, France, England \n","how long is the eiffel tower ?\n 324m, 354m, 412m \n",
"What is the heaviest metal \n Iron, Copper, Uraniam \n "
]
questions = [
Question(question_prompts[4], "uraniam"),
Question(question_prompts[0], "1956"),
Question(question_prompts[1], "tunis"),
Question(question_prompts[2], "france"),
Question(question_prompts[3], "324m")
]
s = tk.StringVar()
useranwser = tk.StringVar()
q = tk.Label(win,textvariable = s)
q.grid(row = 0, column = 0)
u_answer = tk.Entry(win, textvariable = useranwser)
u_answer.grid(row = 1, column = 0)
b = tk.Button(win, text ="Submit", command = ask)
b.grid(row = 2, column =0 )
s.set(questions[0].prompt)#Set the initial question
win.mainloop()

I had to flip this if statment from this :
if useranwser.get() in questions[0].answer:
print("Correct")
score += 1
to this:
if questions[0].answer in useranwser.get():
print("Correct")
score += 1
Thanks to #justin ezequiel for the solution and #random davis for a debugging tip

Related

How to use entry widgets in Tkinter in a loop

I'm creating a Mad Libs game that has a lot of user inputs. I created a function to get all inputs in a list, given a list of the word types. There's no error message, but the window is blank. I tried printing the wordInputs list, and it comes up with:
[<bound method StringVar.get of <tkinter.StringVar object at 0x108763fd0>>,
and so forth. I presume this is because it deleted all of the widgets, but I figured it would do that only after I typed them in. I'm not exactly sure how to store the input into a variable either; do I create a button for that or something? Here's the code:
from tkinter import *
class Game:
#Gets user input for a specified type of word
def getWord(self, words):
wordInputs = []
for i in range(len(words)):
frame = Frame(self.windowSnowDay)
frame.pack()
Label(frame, text = "\nSnow Day\n________\n").grid(row = 1, column = 1, columnspan = 2)
Label(frame, text = "Enter a(n) " + words[i] + ":").grid(row = 2, column = 1)
word = StringVar()
Entry(frame, textvariable = word).grid(row = i + 2, column = 2)
wordInputs.append(word.get)
frame.destroy()
return wordInputs
#Executes "Snow Day" story from Mad Libs menu
def snowDay(self):
self.windowMadLibs.destroy()
self.windowSnowDay = Tk()
self.windowSnowDay.title("Snow Day")
self.windowSnowDay.geometry("200x200")
frame = Frame(self.windowSnowDay)
frame.pack()
#Collects words and stores them in a list
words = ["verb", "electronic device", "public place", "adjective", "verb ending with -ing", "color", "noun", "noun", "drink", \
"clothing item", "adjective", "3-dimensional shape", "adjective", "plural noun", "adjective", "feeling (adjective)", "food"]
wordInputs = self.getWord(words)
print(wordInputs)
self.windowSnowDay.mainloop()
#Prints "Snow Day" story with all inputted words
print("\nAll the children cheer in", emotion, "as they", verb, "that morning. They hear on the", device,"that the", place, end =' ')
print("is closed because of a snowstorm. They think of all the", adj, "things they could do today, such as", verb1, "on a", end = ' ')
print(color, noun + ". Maybe they can even make a snow" + noun1 + "! They go inside, where a warm cup of", drink, "awaits", end = ' ')
print("them. Before going outside, they put on their scarves and", clothing, "so that they don't get", adj1 + ". They", end = ' ')
print("make a snow" + noun1, "out of 3 large", shape + "s, but it quickly fell apart because the snow wasn't very", adj2, end = '. ')
print("After that, one of the", noun2, "attacked another, and it turned into a", adj3, "snowball fight. They were so", feeling, end = ' that ')
print("they went straight to bed. Oh well, I guess they can eat the leftovers of Mom's famous", food, "tomorrow!")
#Main function for Mad Libs
def madLibs(self):
self.windowMadLibs = Tk()
self.windowMadLibs.title("Mad Libs")
self.windowMadLibs.geometry("200x200")
frame = Frame(self.windowMadLibs)
frame.pack()
Label(frame, text = "\nMad Libs\n________\n").grid(row = 1, column = 1)
Button(frame, text = "Snow Day", command = self.snowDay).grid(row = 2, column = 1)
self.windowMadLibs.mainloop()
The main issue is it does not wait for user input, so it's basically going through the loop with all blank values in the entry, then nothing is filled.
(See my comments in the code for more detail)
The bound method StringVar.get result is from wordInputs.append(word.get) instead of wordInputs.append(word.get())
Also, multiple Tk() and .mainloop() calls tend to gum up the works.
This will get it going again, but window re-sizing will need to be addressed,
The prints reference variables that will need to be filled in, you may want a dictionary versus a list:
from tkinter import *
class Game:
#Gets user input for a specified type of word
def getWord(self, words):
wordInputs = []
for i in range(len(words)):
frame = Frame(self.windowSnowDay)
frame.pack()
Label(frame, text = "\nSnow Day\n________\n").grid(row = 1, column = 1, columnspan = 2)
Label(frame, text = "Enter a(n) " + words[i] + ":").grid(row = 2, column = 1)
word = StringVar()
entry = Entry(frame)
entry.grid(row = i + 2, column = 2)
button = Button(frame, text = "Done", command = lambda: word.set(entry.get()))
button.grid(row = i + 3, column = 2)
button.wait_variable(word) # waits for button to be activated and sets the variable.
wordInputs.append(word.get())
frame.destroy()
return wordInputs
#Executes "Snow Day" story from Mad Libs menu
def snowDay(self):
self.windowMadLibs.withdraw() # withdraw the main window.
self.windowSnowDay = Toplevel(self.windowMadLibs) # create a Toplevel instead of a new main.
self.windowSnowDay.title("Snow Day")
self.windowSnowDay.geometry("200x200")
frame = Frame(self.windowSnowDay)
frame.pack()
#Collects words and stores them in a list
words = ["verb", "electronic device", "public place", "adjective", "verb ending with -ing", "color", "noun", "noun", "drink", \
"clothing item", "adjective", "3-dimensional shape", "adjective", "plural noun", "adjective", "feeling (adjective)", "food"]
wordInputs = self.getWord(words)
print(wordInputs)
#Prints "Snow Day" story with all inputted words
print("\nAll the children cheer in", emotion, "as they", verb, "that morning. They hear on the", device,"that the", place, end =' ')
print("is closed because of a snowstorm. They think of all the", adj, "things they could do today, such as", verb1, "on a", end = ' ')
print(color, noun + ". Maybe they can even make a snow" + noun1 + "! They go inside, where a warm cup of", drink, "awaits", end = ' ')
print("them. Before going outside, they put on their scarves and", clothing, "so that they don't get", adj1 + ". They", end = ' ')
print("make a snow" + noun1, "out of 3 large", shape + "s, but it quickly fell apart because the snow wasn't very", adj2, end = '. ')
print("After that, one of the", noun2, "attacked another, and it turned into a", adj3, "snowball fight. They were so", feeling, end = ' that ')
print("they went straight to bed. Oh well, I guess they can eat the leftovers of Mom's famous", food, "tomorrow!")
#Main function for Mad Libs
def madLibs(self):
self.windowMadLibs = Tk()
self.windowMadLibs.title("Mad Libs")
self.windowMadLibs.geometry("200x200")
frame = Frame(self.windowMadLibs)
frame.pack()
Label(frame, text = "\nMad Libs\n________\n").grid(row = 1, column = 1)
Button(frame, text = "Snow Day", command = self.snowDay).grid(row = 2, column = 1)
self.windowMadLibs.mainloop()
g = Game()
g.madLibs()

How do I add colour to this specific code using Colorama in python?

This is my code:
import colorama
from colorama import Fore, Back, Style
import random
colorama.init()
score = int(0)
#--------------------------------------------------------------------#
q1 = ("Work out the answer. 45 + 46 = ")
q2 = ("Kai buys a pair of shoes for £31 and a shirt for £67. Altogether, he spends £")
q3 = ("Work out the answer. 68 - 29 = ")
q4 = ("A bike normally costs £260. Its price is reduced in a sale by £90. The sale price of the bike is ")
q5 = ("Work out the answer. 32 x 30 = ")
q6 = ("A box holds 22 apples. The total number of apples in 20 boxes are ")
q7 = ("Work out the answer. 70 x 7 = ")
q8 = ("For a school show, 22 chairs are arranged equally in 30 rows. The total number of chairs is ")
q9 = ("A function machine changes 49 to 98 and changes 26 to '?'. The number in the question mark is ")
q10 = ("What number fills the gap? 35 x ? = 105. The number is ")
question = [
(q1, "91"),
(q2, "98"),
(q3, "39"),
(q4, "170"),
(q5, "960"),
(q6, "440"),
(q7, "490"),
(q8, "660"),
(q9, "52"),
(q10, "3")
]
comments = ["Correct, you get one point, onto the next question", "At least I'm not the only smart one around here",
"Well done", "You must be really smart", "Some people have actually failed at that question...",
"Congratulations", "Good work I guess...", "You actually got that right?!"]
bcomments = ["Too bad, I have to take a point away, but I bet you got that wrong on purpose. Right...?",
"I'm stealing your points!","You're a disgrace to mathematics",
"You can't be serious... Can you?","Oops to you too...","Throw me your points!!",
"Did you read the question properly?","Too bad...","I'm running out of ways to take your points...","Did you have to get it wrong??"]
colour = [(Fore.BLACK + Back.WHITE), (Fore.RED + Back.BLUE)]
This last line is the line where I have identified two colours to use using Colorama
random.shuffle(question)
for question, correctanswer in question:
answer = input(question + "")
if answer == correctanswer:
correctA = 1
print(comments[random.randrange(len(comments))])
score = score + int(1)
print("Your current score is " + str(score))
else:
print("Wrong, the Correct answer is " + correctanswer)
print(bcomments[random.randrange(len(bcomments))])
if score>0:
score = score - int(1)
print("Your current score is " + str(score))
#--------------------------------------------------------------------#
input()
If I wanted to add colour to each presented question how would I do this? For example, how would I edit my code so that each question was displayed in a different colour?

Python 3 and Tkinter- how to control a quiz loop

I'm sure the answer to this is obvious but I cannot spot it! I have a very basic quiz(using Tkinter and Python 3) which uses 2 arrays , the question is displayed and then the answer entered is matched using the array index when the submit button is clicked.
The question at index 0 is displayed twice- cannot see why
The score does not increment correctly- even though it is a global variable- it just shows 1 each time.
How can I get the quiz to move to a print statement after the end of the list is reached?
I have tried putting an IF statement in the submit function to check the value of i but cannot get this to work. Can anyone point out my errors please?
from tkinter import *
global questions
questions =["What is the name of the Simpsons' next door neighbour?","What is the name of the school bus driver?",
"Who runs the Kwik-e-mart?","What does Bart do at the end of the opening credits?"]
global answers
answers = [ "Ned Flanders","Otto","Apu","Write On The Blackboard"]
global score
score = 0
global i
i = 0
def submit():
'''runs the submit button'''
global i
global score
question.config(text=questions[i])
if answer.get().lower()==answers[i].lower():
score+=1
else:
score=score
i+=1
scoretxt.config(text =str(score))
answer.delete(0,END)
window = Tk()
window.title("Simpsons Quiz")
window.wm_iconbitmap("homer.ico")
window.configure(background ="#ffd600")
banner = PhotoImage(file ="the-simpsons-banner.gif")
Label(window,image = banner).grid(row = 0,columnspan = 6)
Label(window,text = "Question : ",bg ="#ffd600",justify=LEFT).grid(row = 1,column = 0)
Label(window,text = "Type answer here: ",bg = "#ffd600",justify=LEFT).grid(row = 3, column = 0)
scoreLabel =Label(window,bg = "#ffd600")
scoretxt = Label(window,text ="Your score is: ?",bg = "#ffd600")
scoreLabel.grid(row=5,column = 2)
scoretxt.grid(row = 6,column = 2)
question=Label(window,bg = "white",text= questions[0],justify=LEFT)
question.grid(row =1,column=1)
answer = Entry(window,bg ="white",width = 30)
answer.grid(row = 3,column=1)
# make a submit button
Button(window,text= "Submit",bg = "white",command = submit).grid(row = 3,column = 2)
mainloop()
1) You are printing the question before you increment i. That's why you get twice.
2) It is always 1 becuase of your usage of global. In python you use global keyword in which scope you want to change your variable. Sadly, my english is not good enough to explain this. Please check out these answers.
3) You can use try-except block. I used it there because that is the exact line where you get the error. You can expand its range.
from tkinter import *
questions =["What is the name of the Simpsons' next door neighbour?","What is the name of the school bus driver?",
"Who runs the Kwik-e-mart?","What does Bart do at the end of the opening credits?"]
answers = [ "Ned Flanders","Otto","Apu","Write On The Blackboard"]
#removed globals from here
score = 0
i = 0
def submit():
'''runs the submit button'''
global i
global score
if answer.get().lower()==answers[i].lower():
score+=1
i+=1 #first increment, then show the question since you already show it at startup
try: #since you get the IndexError on this line, I used on here
question.config(text=questions[i])
except IndexError:
print ("something")
scoretxt.config(text = "Your score is: {}".format(str(score)))
answer.delete(0,END)
window = Tk()
window.title("Simpsons Quiz")
window.wm_iconbitmap("homer.ico")
window.configure(background ="#ffd600")
banner = PhotoImage(file ="the-simpsons-banner.gif")
Label(window,image = banner).grid(row = 0,columnspan = 6)
Label(window,text = "Question : ",bg ="#ffd600",justify=LEFT).grid(row = 1,column = 0)
Label(window,text = "Type answer here: ",bg = "#ffd600",justify=LEFT).grid(row = 3, column = 0)
scoreLabel =Label(window,bg = "#ffd600")
scoretxt = Label(window,text ="Your score is: ?",bg = "#ffd600")
scoreLabel.grid(row=5,column = 2)
scoretxt.grid(row = 6,column = 2)
question=Label(window,bg = "white",text= questions[0],justify=LEFT)
question.grid(row =1,column=1)
answer = Entry(window,bg ="white",width = 30)
answer.grid(row = 3,column=1)
# make a submit button
Button(window,text= "Submit",bg = "white",command = submit).grid(row = 3,column = 2)
mainloop()
Also you might want to use a dictionary instead of questions-answers lists.

Python custom modules - error with example code

I am reading the book "Python Programming for the Absolute Beginner (3rd edition)". I am in the chapter introducing custom modules and I believe this may be an error in the coding in the book, because I have checked it 5 or 6 times and matched it exactly.
First we have a custom module games.py
class Player(object):
""" A player for a game. """
def __init__(self, name, score = 0):
self.name = name
self.score = score
def __str__(self):
rep = self.name + ":\t" + str(self.score)
return rep
def ask_yes_no(question):
""" Ask a yes or no question. """
response = None
while response not in ("y", "n"):
response = input(question).lower()
return response
def ask_number(question, low, high):
""" Ask for a number within a range """
response = None
while response not in range (low, high):
response = int(input(question))
return response
if __name__ == "__main__":
print("You ran this module directly (and did not 'import' it).")
input("\n\nPress the enter key to exit.")
And now the SimpleGame.py
import games, random
print("Welcome to the world's simplest game!\n")
again = None
while again != "n":
players = []
num = games.ask_number(question = "How many players? (2 - 5): ", low = 2, high = 5)
for i in range(num):
name = input("Player name: ")
score = random.randrange(100) + 1
player = games.Player(name, score)
players.append(player)
print("\nHere are the game results:")
for player in players:
print(player)
again = games.ask_yes_no("\nDo you want to play again? (y/n): ")
input("\n\nPress the enter key to exit.")
So this is exactly how the code appears in the book. When I run the program I get the error IndentationError at for i in range(num):. I expected this would happen so I changed it and removed 1 tab or 4 spaces in front of each line from for i in range(num) to again = games.ask_yes_no("\nDo you want to play again? (y/n): ").
After this the output is "Welcome to the world's simplest game!" and that's it.
I was wondering if someone could let me know why this is happening?
Also, the import games module, is recognized in Eclipse after I added the path to PYTHONPATH.
I actually have this book myself. And yes, it is a typo. Here is how to fix it:
# SimpleGame.py
import games, random
print("Welcome to the world's simplest game!\n")
again = None
while again != "n":
players = []
num = games.ask_number(question = "How many players? (2 - 5): ", low = 2, high = 5)
for i in range(num):
name = input("Player name: ")
score = random.randrange(100) + 1
player = games.Player(name, score)
players.append(player)
print("\nHere are the game results:")
for player in players:
print(player)
again = games.ask_yes_no("\nDo you want to play again? (y/n): ")
input("\n\nPress the enter key to exit.")
All I did was indent num 4 spaces and lined it up with the first for-loop.
You have an infinite loop here:
again = None
while again != "n":
players = []
If this is exactly the way it's printed in the book, the book does have an error.
You've got these two lines:
num = games.ask_number(question = "How many players? (2 - 5): ", low = 2, high = 5)
for i in range(num):
The second one is more indented than the first. That's only legal if the first one is a block-introducer like a for or while or if. Since it's not, this is an IndentationError. And that's exactly what Python is telling you.
(It's possible that you've copied things wrong. It's also possible that you're mixing tabs and spaces, so it actually looks right in your editor, but it looks wrong to Python. But if neither of those is true, the book is wrong.)
So, you attempted to fix it by dedenting everything from that for loop on.
But when you do that, only one line is still left under the while loop:
while again != "n":
players = []
There's nothing that can possibly change again to "n", so this will just spin forever, doing nothing, and not moving on to the rest of the program.
So, what you probably want to do is to indent the num = … line to the same level as the for i… line, so both of them (and all the stuff after) ends up inside the while loop.

How do I make radiobuttons assign either a 0,1,2 or 3 to my variables?

Here is a rough example of a multiple choice test that I made. It runs in terminal and I'm hoping to make a Graphical User Interface for it using Tkinter.
print "CATEGORY 1: ANXIOUS FEELINGS"
print
print "1. Anxiety, nervousness, worry or fear"
BAI_var1 = input ("Please enter 0 for not at all, 1 for somewhat, 2 for moderatly or 3 for a lot:")
print
print "2. Feeling that things around you are strange, unreal, or foggy"
BAI_var2 = input ("Please enter 0 for not at all, 1 for somewhat, 2 for moderatly or 3 for a lot:")
print
print "3. Feeling detached from all or part of your body"
BAI_var3 = input ("Please enter 0 for not at all, 1 for somewhat, 2 for moderatly or 3 for a lot:")
print "Depression Test"
print
print
print "1. Sadness: Have been feeling sad or down in the dumps?"
BDC_var1 = input ("Please enter 0 for not at all, 1 for somewhat, 2 for moderatly or 3 for a lot:")
print
print "2. Discouragement: Does the future look hopeless?"
BDC_var2 = input ("Please enter 0 for not at all, 1 for somewhat, 2 for moderatly or 3 for a lot:")
print
print "3. Low self-esteem: Do you feel worthless or think of yourself as a failure?"
BDC_var3 = input ("Please enter 0 for not at all, 1 for somewhat, 2 for moderatly or 3 for a lot:")
#Burns Anxiety Inventory
#CATEGORY 1: ANXIOUS FEELINGS
Cat1_var = BAI_var1 + BAI_var2 + BAI_var3
#Burns Anxiety Checklist
BAI_var = Cat1_var
#Burns Depression Checklist
BDC_var = BDC_var1 + BDC_var2 + BDC_var3
#Prints your BAI & your BDC
print "Your BAI =", BAI_var,"Your BDC =", BDC_var
name = raw_input ("Please type in your name:")
bai = str(input("Please enter your BAI:"))
bdc = str(input("Please enter your BDC:"))
year = str(input("please enter the year:"))
month = str(input("Please enter the month:"))
day = str(input("Please enter day:"))
time_hour = str(input("Please enter the current hour:"))
time_minute = str(input("Please enter the current minutes:"))
am_pm = raw_input ("Please enter pm or am:")
file = open('Burns inventory 1.3.txt', 'a')
file.write(name + '\n')
file.write(day)
file.write("/")
file.write(month)
file.write("/")
file.write(year)
file.write('\n')
file.write('\n')
file.write('Your BAI is:')
file.write(bai)
file.write('\n')
file.write('Your BDC is:')
file.write(bdc)
file.write('\n')
file.write(time_hour)
file.write(':')
file.write(time_minute)
file.write('\n')
file.write(' ')
file.write(am_pm)
file.write('\n')
file.close()
I have been working for 2 days two teach myself how to use Tkinter. My friend and I made this rough example of what the test might look like.
from Tkinter import *
import time
class App:
def __init__(self, master):
w = Label(master, text="1. Anxiety, nervousness, worry or fear")
w.pack()
v = IntVar()
Radiobutton(master, text="0 for not at all", variable=v, value=1).pack(side=TOP, anchor="w")
Radiobutton(master, text="1 for somewhat", variable=v, value=2).pack(side=TOP, anchor="w")
Radiobutton(master, text="2 for moderatly", variable=v, value=3).pack(side=TOP, anchor="w")
Radiobutton(master, text="3 for a lot", variable=v, value=4).pack(side=TOP, anchor="w")
self.button = Button(master, text="BACK", fg="red", command=self.button6)
self.button.pack(side=BOTTOM)
self.button = Button(master, text="NEXT", fg="red", command=self.button5)
self.button.pack(side=BOTTOM)
def button6(self):
print "Sam is awesome!GAJONGA"
def button5(self):
print "PYTHON FOR THE WIN! GIAN SAYS PYTHON = FILTHY"
master = Tk()
app = App(master)
master.mainloop()
I can think of a few goals with this Tkinter GUI:
Make Radiobuttons assign either a 0,1,2 or 3 to my variables(BAI_var1, BAI_var2, BAI_3 etc.)
Make the "NEXT" & "BACK" buttons show a different question every time you press it.
Make a page at the end of the test that has multiple input fields for name, date, etc.
I did not make the test!! I only made the software. The test was designed by David Burns and is available in his work book "The Feeling Good Book".
change all of the places where you have v with self.v so that it becomes an attribute of the object. You'll then see that it has whatever value is selected in the group of radiobuttons.
...
self.v = IntVar()
...
Radiobutton(master, text="1 for somewhat", variable=self.v, value=2)...
...
Once you do that, in your button5 or button6 method you can do print self.v.get() to see the value.
If you're not interested in learning tkinter right now, easygui would be a good fit for quickly getting a GUI for this test. It's not in the standard library, so you'll have to either install it with pip install or download it and put the easygui.py file in the same folder as your script. Easygui lets you do things like:
import easygui
animal = easygui.choicebox(
msg='Pick an animal.',
title='answer the question',
choices=('dog', 'cat', 'pig')
)
print animal
# prints dog or pig or cat

Categories