TKinter running through a loop - python

For a basic example, suppose I want to run a list of questions and for each question i want a button to be pressed which will append a value "yes" or "no" to the list.
window = tk.Tk()
app=tk.Frame(window)
app.grid()
response_list = []
y_button = tk.Button(app,text="yes", command=lambda x="yes": appendResponse(x))
n_button = tk.Button(app,text="no", command=lambda x="no": appendResponse(x))
questions=["q1","q2","q3"]
window.mainloop()
How can i make the window stay open and display all the questions until there is a complete list of answers?

You can write a function like the following:
#STARTS HERE
#Label with question
lbl1 = tk.Label(app, text="Are you a human?")
lbl1.grid()
def appendResponse(resp):
global response_list
questionNo = len(response_list)
if questionNo % 3 == 0:
lbl1.configure(text="Is this a valid question?")
elif questionNo % 3 == 1:
lbl1.configure(text="Is there a better way to do this?")
elif questionNo % 3 == 2:
lbl1.configure(text="Is this what you wanted to do?")
response_list.append(resp)
#FINISHES HERE

Related

How to reuse a Button action

I am trying to reuse the action of this button, without recalling the command all over again, the thing is that, after the button executes the first "if" statement "y == 1".
Now, instead of having access to the second "if" statement "y == 2" (That is, assume the program starts now, if I enter 1 in the entry box and the button is clicked, the program should print "Yes!", then if I enter 2 again in the entry box and the button is clicked, the program should print "Yes!Yes!", but instead it starts the "def action()" all over again)
I want it to run like the second code if I use a console
from tkinter import *
win = Tk()
def action():
y = x.get()
if y == 1:
print("Yes!")
if y == 2:
print("Yes!Yes!")
elif y == 3:
print("Yes!Yes!Yes!")
else:
print("No")
x = IntVar()
e1 = Entry(win, textvariable = x).grid()
b1 = Button(win, text = "Button", command = action).grid()
win.mainloop()
The second code
y = eval(input("Enter a value: "))
if y == 1:
print("Yes")
y = eval(input("Enter a value: "))
if y == 2:
print("Yes!Yes!")
elif y == 3:
print("Yes!Yes!Yes!")
else:
print("No")
put
y = x.get()
clicked = False
after
b1 = Button(win, text = "Button", command = action).grid()
Now,
def action():
if y == 2 and clicked == True:
print("Yes!Yes!")
if y == 3 and clicked == True:
print("Yes!Yes!Yes!")
if y == 1 and clicked == False:
print("Yes!")
clicked = True
If I understood your question well, this might pop the desired result.
Walrus to rescued.
Code:
from tkinter import *
win = Tk()
def action():
# y = x.get()
if (y := x.get()) == 1:
print("Yes!")
elif y == 2:
txt= 'Yes!'
print(txt*2)
elif y == 3:
txt = 'Yes!'
print(txt*3)
else:
print("No")
x = IntVar()
e1 = Entry(win, textvariable = x).grid()
b1 = Button(win, text = "Button", command = action).grid()
win.mainloop()
Result:
Yes!
Yes!Yes!
Yes!Yes!Yes!
No
if I enter 1 in the entry box and the button is clicked, the program
should print "Yes!", then if I enter 2 again in the entry box and the
button is clicked, the program should print "Yes!Yes!", and so on.
Walrus to rescued.
Code:
from tkinter import *
win = Tk()
def action():
# y = x.get()
if (y := x.get()) == 1:
print("Yes!")
elif y == 2:
txt= 'Yes!'
print(txt*2)
elif y == 3:
txt = 'Yes!'
print(txt*3)
else:
print("No")
x = IntVar()
e1 = Entry(win, textvariable = x).grid()
b1 = Button(win, text = "Button", command = action).grid()
win.mainloop()
Result:
Yes!
Yes!Yes!
Yes!Yes!Yes!
No

Printing textbox input to console with tkinter (python3.7)

I am making tic tac toe in python using tkinter, and the code all works except for when I try to print which player is the winner, I get the following ouput:
The player who won is:
.!entry
The code I used to print out the winner is this:
print("The player who won is: ", e1_entry)
...
where e1_entry is defined as this:
e1_entry = e1.get()
and e1 is:
e1 = tkinter.Entry(window, textvariable=e1_entry)
How would I make it so that the text taken from the tkinter Entry is printed to the console?
Thanks
Gaurav Bhalla
Here is a working example. You would need to define a function to get the string
import tkinter
def getWinner():
n = entry1.get()
if n == "":
n = "Nobody won"
print(n)
root = tkinter.Tk()
entry1 = tkinter.Entry(root)
entry1.grid(row = 0, column = 0)
root.after(10000, getWinner)
root.mainloop()
This has an Entry widget, and after 10 seconds, will call the function 'getWinner'. If the Entry widget has no text in it, there will be no winner.
Hope this helps!
You should try something like:
window = Tk()
text = StringVar()
e1 = Entry(window, textvariable = text)
e1.pack()
e1_entry = text.get()
print("The player who won is:", e1_entry)

Keep track of score

I am trying to make a quiz that shows the user the name of the state and they have to correctly state the capital. Everything works fine, except for keeping track of the user's score. I have tried to change around the score portion of the code, but nothing is working! I think the problem is somewhere in the nextCapital() function, but then again I could be wrong. I am new to python and all of this is a little overwhelming. I would really appreciate the help!
import tkinter
import random
capitals={"Washington":"Olympia","Oregon":"Salem",\
"California":"Sacramento","Ohio":"Columbus",\
"Nebraska":"Lincoln","Colorado":"Denver",\
"Michigan":"Lansing","Massachusetts":"Boston",\
"Florida":"Tallahassee","Texas":"Austin",\
"Oklahoma":"Oklahoma City","Hawaii":"Honolulu",\
"Alaska":"Juneau","Utah":"Salt Lake City",\
"New Mexico":"Santa Fe","North Dakota":"Bismarck",\
"South Dakota":"Pierre","West Virginia":"Charleston",\
"Virginia":"Richmond","New Jersey":"Trenton",\
"Minnesota":"Saint Paul","Illinois":"Springfield",\
"Indiana":"Indianapolis","Kentucky":"Frankfort",\
"Tennessee":"Nashville","Georgia":"Atlanta",\
"Alabama":"Montgomery","Mississippi":"Jackson",\
"North Carolina":"Raleigh","South Carolina":"Columbia",\
"Maine":"Augusta","Vermont":"Montpelier",\
"New Hampshire":"Concord","Connecticut":"Hartford",\
"Rhode Island":"Providence","Wyoming":"Cheyenne",\
"Montana":"Helena","Kansas":"Topeka",\
"Iowa":"Des Moines","Pennsylvania":"Harrisburg",\
"Maryland":"Annapolis","Missouri":"Jefferson City",\
"Arizona":"Phoenix","Nevada":"Carson City",\
"New York":"Albany","Wisconsin":"Madison",\
"Delaware":"Dover","Idaho":"Boise",\
"Arkansas":"Little Rock","Louisiana":"Baton Rouge"}
score=0
timeleft=30
print("This program will launch a capital quiz game.")
input1 = input("What difficulty would you like to play: easy, normal, or hard?\n")
if input1.lower() == "easy":
seconds = 90
timeleft = seconds
elif input1.lower() == "normal":
seconds = 60
timeleft = seconds
elif input1.lower() == "hard":
seconds = 30
timeleft = seconds
def startGame(event):
#if there's still time left...
if timeleft == seconds:
#start the countdown timer.
countdown()
#run the function to choose the next colour.
nextCapital()
if timeleft == 0:
endlabel = tkinter.Label(root, text="The time is up!\nYour score is: " + str(score) +" out of 50", font=('Helvetica', 12))
endlabel.pack()
e.pack_forget()
#function to choose and display the next colour.
def nextCapital():
#use the globally declared 'score' and 'play' variables above.
global score
global timeleft
#if a game is currently in play...
if timeleft > 0:
#...make the text entry box active.
e.focus_set()
randchoice = random.choice(list(capitals.keys()))
answer = capitals.get(randchoice)
if answer.lower() == randchoice.lower():
score = score+1
#### #this deletes the random choice from the dictionary
#### del capitals[randchoice]
#clear the text entry box.
e.delete(0, tkinter.END)
#this updates the random choice label
label.config(text=str(randchoice))
#update the score.
scoreLabel.config(text="Score: " + str(score))
#a countdown timer function.
def countdown():
#use the globally declared 'play' variable above.
global timeleft
#if a game is in play...
if timeleft > 0:
#decrement the timer.
timeleft -= 1
#update the time left label.
timeLabel.config(text="Time left: " + str(timeleft))
#run the function again after 1 second.
timeLabel.after(1000, countdown)
#create a GUI window.
root = tkinter.Tk()
#set the title.
root.title("Capital Quiz")
#set the size.
root.geometry("500x250")
#add an instructions label.
instructions = tkinter.Label(root, text="Brush up your geography skills!", font=('Helvetica', 12))
instructions.pack()
#add a score label.
scoreLabel = tkinter.Label(root, text="Press enter to start" + str(score), font=('Helvetica', 12))
scoreLabel.pack()
#add a time left label.
timeLabel = tkinter.Label(root, text="Time left: " + str(timeleft), font=('Helvetica', 12))
timeLabel.pack()
#prompt label
promptLabel = tkinter.Label(root, text= "Enter the capital of: ", font=('Helvetica', 12))
promptLabel.pack()
#add a label that will hold print the prompt
label = tkinter.Label(root, font=('Helvetica', 60))
label.pack()
#add a text entry box for typing in colours.
e = tkinter.Entry(root)
#run the 'startGame' function when the enter key is pressed.
root.bind('<Return>', startGame)
e.pack()
#set focus on the entry box.
e.focus_set()
#start the GUI
root.mainloop()
randchoice is one of the keys in the capitals dict, i.e. a State.
answer is one of the values in the capitals dict, i.e. a Capital
You then compare the lowercase versions of randchoice and answer and increment the score if they are equal. But clearly they will never be equal (one is a State, one is a Capital). So your score won't be updated properly.
Not an answer, but a bit of advice: eschew all global variables, wrap things into an object with clearly defined, short methods. You will have much easier time working with and reasoning about the code.
Consider this skeleton of a class:
class Quiz(object):
def __init__(self, difficulty, capitals_dict):
self.score = 0
self.capitals = capitals
self.difficulty = ...
self.right_answer = None
def getNextQuestion(self):
# Choose a capital and assign it as the current right answer
...
self.right_answer = ...
return self.right_answer # to show it to user
def checkAnswer(user_answer):
if user_answer == self.right_answer:
self.score = ...
return True
else:
...
def isGameOver(self):
return len(self.capitals) == 0
I guess it's clear enough how to use a class like this, and reasonably clear how to implement it.

tkinter: How to change labels inside the program itself

I was asked to edit my code so I decided to include the entire calculator script
from tkinter import *
global choice
choice = 0
#Program
def calculate(*event):
if choice == 1:
try:
add1 = ccalc1.get()
add2 = ccalc2.get()
except:
no = Label(app, text="You must use a number").grid(row=0, column=0)
answ = add1 + add2
answer = Label(app, text = answ).grid(row=1, column=0)
elif choice == 2:
try:
sub1 = ccalc1.get()
sub2 = ccalc2.get()
except:
no = Label(app, text="You must use a number").grid(row=1, column=0)
answ = sub1 - sub2
answer = Label(app, text = answ).grid(row=1, column=0)
def choice2():
global choice
choice = 2
#End Program
#GUI
#Window Info
calc = Tk()
calc.title("Calculator")
calc.geometry("200x140")
#End Window Info
#Build Window
app = Frame(calc)
app.grid()
ccalc1 = IntVar()
ccalc2 = IntVar()
#Widgets
if choice == 0:
welcome = Label(app, text="Select a choice")
elif choice == 2:
welcome.config(text="Subtraction")
calcbox1 = Entry(app,textvariable=ccalc1)
calcbox2 = Entry(app,textvariable=ccalc2)
submit = Button(app, text="CALCULATE", command = calculate)
welcome.grid(row=0,column=0)
calcbox1.grid(row=2, column=0)
calcbox2.grid(row=3, column=0)
submit.grid(row=4, column=0)
calc.bind('<Return>', calculate)
#End Widgets
#Menu
menu=Menu(calc)
#Operations
filemenu = Menu(menu,tearoff=0)
filemenu.add_command(label="Subtract", command = choice2)
menu.add_cascade(label="Operations",menu=filemenu)
calc.config(menu=menu)
calc.mainloop()
#End GUI
what wrong is that the welcome label text wont change accordingly.
Update: I included the entire calculator code
Any help is appreciated.
It's hard to understand what you expect to happen. For example, look at this code:
#Widgets
if choice == 0:
welcome = Label(app, text="Select a choice")
elif choice == 2:
welcome.config(text="Subtraction")
This code will only ever execute once, and choice will always be zero since that's what you initialize it to. It executes once because it's not in a function and not in a loop, so as python parses the code it will run it and move to the next line. That block of text will never be processed a second time.
If you want the label to change when the user selects a menu item, you'll need to execute that code inside the choice2 function:
def choice2():
global choice
choice = 2
welcome.config(text="Subtraction")

Creating a Tkinter math Quiz

I am learning python and am having trouble getting this program to work correctly.
from Tkinter import*
import time
import tkMessageBox
import random
def Questions():
number1 = random.randrange(1,25,1)
number2 = random.randrange(1,50,2)
answer = number1 + number2
prompt = ("Add " + str(number1) + " and " + str(number2))
label1 = Label(root, text=prompt, width=len(prompt), bg='yellow')
label1.pack()
return answer
def start():
global count_flag
Questions()
count_flag = True
count = 0.0
while True:
if count_flag == False:
break
# put the count value into the label
label['text'] = str(count)
# wait for 0.1 seconds
time.sleep(0.1)
# needed with time.sleep()
root.update()
# increase count
count += 0.1
def Submit(answer, entryWidget):
""" Display the Entry text value. """
global count_flag
count_flag = False
print answer
if entryWidget.get().strip() == "":
tkMessageBox.showerror("Tkinter Entry Widget", "Please enter a number.")
if int(answer) != entryWidget.get().strip():
tkMessageBox.showinfo("Answer", "INCORRECT!")
else:
tkMessageBox.showinfo("Answer", "CORRECT!")
# create a Tkinter window
root = Tk()
root.title("Math Quiz")
root["padx"] = 40
root["pady"] = 20
# Create a text frame to hold the text Label and the Entry widget
textFrame = Frame(root)
#Create a Label in textFrame
entryLabel = Label(textFrame)
entryLabel["text"] = "Answer:"
entryLabel.pack(side=LEFT)
# Create an Entry Widget in textFrame
entryWidget = Entry(textFrame)
entryWidget["width"] = 50
entryWidget.pack(side=LEFT)
textFrame.pack()
#directions
directions = ('Click start to begin. You will be asked a series of questions like the one below.')
instructions = Label(root, text=directions, width=len(directions), bg='orange')
instructions.pack()
# this will be a global flag
count_flag = True
answer = Questions()
Sub = lambda: Submit(answer, entryWidget)
# create needed widgets
label = Label(root, text='0.0')
btn_submit = Button(root, text="Submit", command = Sub)
btn_start = Button(root, text="Start", command = start)
btn_submit.pack()
btn_start.pack()
label.pack()
# start the event loop
root.mainloop()
It just says "INCORRECT!" every time I push submit regardless of what I enter into the text box. Any suggestions would be appreciated. Thanks, Scott
Left side is an integer, right side is a string, so it's always False:
int(answer) != entryWidget.get().strip()
You can try:
int(answer) != int(entryWidget.get().strip())

Categories