How to set up multiple frames - python

This is a simple math game which is currently in progress. The loop starts off in mainGame() which then proceeds to mainMenu(). I am trying to create 2 frames; mframe and gframe in order to .destroy() the frames later on, essentially clearing the previous interface for the next one (similar to changing pages).
error:
Label(gframe, textvariable=self.question_var).pack() #gframe stands
for game frame NameError: name 'gframe' is not defined
from tkinter import *
from random import randint
root = Tk()
mframe = Frame(root).pack()
gframe = Frame(root).pack()
frame.pack()
start = True
class mainMenu:
def __init__(self):
gframe.destroy() #gets rid of previous interface
title = Label(mframe, text = "main menu").pack() #mfame stands for menu frame
class mainGame:
def __init__(self):
if start == False:
mframe.destroy() #gets rid of previous interface
#question
self.question_var = StringVar()
Label(gframe, textvariable=self.question_var).pack() #gframe stands for game frame
#answer
self.user_answer_var = StringVar()
entry = Entry(gframe, textvariable=self.user_answer_var)
entry.pack()
submit = Button(gframe, text = "submit", command = self.check_answer).pack()
#response output
self.response_var = StringVar()
self.count = 0
self.score = 0
Label(gframe, textvariable=self.response_var).pack()
#starts loop
self.ask_question()
root.mainloop()
def ask_question(self):
if self.count == 1:
self.endGame()
num1 = randint(1, 10)
num2 = randint(1, 10)
self.question_var.set("What is "+str(num1)+" + " +str(num2)+"?")
self.true_answer = num1 + num2
#print(self.true_answer) #testing purposes
def check_answer(self):
self.count += 1
user_answer = self.user_answer_var.get()
#print(user_answer) #testing purposes
if int(user_answer) == self.true_answer:
text = "Good job"
self.score += 1
else:
text = "Oh no"
self.response_var.set(text)
#clear answer for next loop
self.user_answer_var.set("")
self.ask_question()
def endGame(self):
print("endGame")
mainMenu()
mainGame()

As said in the comments above, the pack() method returns None. What you need to do is first create the two frames and assign them to variables, then pack them later. This way, the variables still point to the frame instances and not None.
You should change;
root = Tk()
mframe = Frame(root).pack()
gframe = Frame(root).pack()
frame.pack()
start = True
to;
root = Tk()
mframe = Frame(root)
gframe = Frame(root)
mframe.pack()
gframe.pack()
start = True

Related

.delete("1.0",END) not clearing textbox

Ive been coding a maths game but stumbled across a problem where I cant clear a text widget. SO after the users get shown a list of incorrect questions and to play the game again, but after playing the game a second time the list doesn't reset. I've added a comment above the text widget I want to clear if that helps.
from tkinter import *
import random
from tkinter import messagebox
class Timestable:
def __init__(self, parent):
Timestable.f1 = Frame(parent,bg='#66bcb9')
Timestable.f1.grid()
Timestable.f2 = Frame(parent,bg='#66bcb9')
Timestable.f2.grid()
Timestable.f2.grid_forget()
Timestable.f3 = Frame(parent,bg='#66bcb9')
Timestable.f3.grid()
Timestable.f3.grid_forget()
Timestable.f4 = Frame(parent,bg='#66bcb9')
Timestable.f4.grid()
Timestable.f4.grid_forget()
#frame 1 ========================================================
Label(self.f1,text="Multiplication Practice",bg='#508484',fg='white').grid(columnspan=2,column=0,row=0)
Label(self.f1,text="Name:",bg='#508484',fg='white').grid(row=1,column=0)
Timestable.name = Entry (self.f1)
Timestable.name.grid(row=1,column=1)
Label(self.f1,text="Age",bg='#508484',fg='white').grid(row=2,column=0)
Timestable.age = Entry (self.f1)
Timestable.age.grid(row=2,column=1)
Timestable.incorrect=[]
Timestable.user = []
Timestable.checked = []
Label(self.f1,text="Select Timestable",bg='#508484',fg='white').grid(columnspan=2,row=3,column=0)
frame = Frame(self.f1)
frame.grid(row=5,column=0, columnspan=2)
for i in range(12):
Timestable.checked.append(IntVar()) # store the tkinter variable for the checkbox
Checkbutton(frame, text=i+1, variable=self.checked[-1], onvalue=i+1, offvalue=0, anchor='w',bg='#66bcb9').grid(row=i//3, column=i%3, sticky='ew')
Label(self.f1,text="Total Questions",bg='#508484',fg='white').grid(row=4,column=0)
Timestable.w = Spinbox(self.f1, from_=1, to=5)
Timestable.w.grid(row=4,column=1)
Button(self.f1,text="Start", command=lambda: data.start(self),bg='#88c43c').grid(columnspan=2, column=0,row=6)
#frame 2 ========================================================
Label(self.f2,text="Multiplication Practice",bg='#508484',fg='white').grid(columnspan=2,column=0,row=0)
self.x=0
self.correct=0
Timestable.questions=Label(Timestable.f2,text="")
Timestable.questions.grid(row=1,column=0)
Timestable.entryWidget = Entry (self.f2)
Timestable.entryWidget.grid(row=1,column=1)
Button(self.f2,text="submit", command=lambda: data.Submit(self),bg='#88c43c').grid(columnspan=2,column=0,row=3)
#frame 3 ========================================================
Label(self.f3,text="Multiplication Practice",bg='#508484',fg='white').grid(columnspan=2,column=0,row=0)
Timestable.congrats=Label(Timestable.f3,text="")
Timestable.congrats.grid(columnspan=2,column=0,row=1)
#this is the widget I want to clear
Timestable.incdisplay = Text(Timestable.f3, width=15,height=10,bg='#d0e4f4')
Timestable.incdisplay.grid(columnspan=2,column=0,row=2)
Button(self.f3,text="next", command=lambda:data.next(self),bg='#88c43c').grid(columnspan=2,column=0,row=3)
#fram 4 ========================================================
Label(self.f4,text="Multiplication Practice",bg='#508484',fg='white').grid(columnspan=2,column=0,row=0)
Label(self.f4,text="Results",bg='#508484',fg='white').grid(columnspan=2,column=0,row=1)
Timestable.my_text=Text(self.f4,width=20,height=10,bg='#d0e4f4')
Timestable.my_text.grid(columnspan=2,column=1,row=2)
Button(self.f4,text="again", command=lambda:data.again(self),bg='#88c43c').grid(columnspan=2,column=0,row=3)
class data:
def saveleader(self):
file=open('Leaderboard.txt',"a")
file.write(Timestable.name.get()+","+Timestable.age.get()+","+str(data.percent)+"%""\n")
file.close
file=open("Leaderboard.txt","r").read()
headers = " ".join(["Name", "Age", "Score"])
output = [i.split(",") for i in file.split("\n") if i]
out_sort = sorted(output, key=lambda x: int(x[2][:-1]), reverse=True)
final = "\n".join([headers, "-"*len(headers),*(" ".join(i) for i in out_sort)])
Timestable.my_text.insert(END, final)
def clear_text(self):
Timestable.entryWidget.delete(0, 'end')
def Questions(self):
number1 = random.choice(Timestable.user)
number2 = random.randrange(1,12)
self.answer = number1 * number2
self.prompt = (str(number1) + " X " + str(number2))
Timestable.questions.configure(text=self.prompt, width=len(self.prompt),bg='#66bcb9')
return self.answer
def start(self):
Timestable.user = [v.get() for v in Timestable.checked if v.get()]
if Timestable.user:
Timestable.f1.grid_forget()
Timestable.f2.grid()
data.Questions(self)
def results(self):
Timestable.f2.grid_forget()
Timestable.f3.grid()
def next(self):
Timestable.f3.grid_forget()
Timestable.f4.grid()
data.saveleader(self)
self.correct=0
data.deletold(self)
def again(self):
Timestable.f4.grid_forget()
Timestable.f1.grid()
def deletold(self):
Timestable.incdisplay.configure(state=NORMAL)
Timestable.incdisplay.delete("1.0",END)
Timestable.incdisplay.configure(state=DISABLED)
def Submit(self):
if Timestable.entryWidget.get() == "":
messagebox.showerror("Error", "Please enter a number.")
else:
if self.answer != int(Timestable.entryWidget.get().strip()):
messagebox.showinfo("Answer", "INCORRECT! Answer: " + str(self.answer))
Timestable.incorrect.append(self.prompt+"\n")
else:
messagebox.showinfo("Answer", "CORRECT!")
self.correct = self.correct +1
self.x=self.x+1
if self.x < int(Timestable.w.get()):
data.Questions(self)
data.clear_text(self)
else:
data.clear_text(self)
data.results(self)
data.percent = round(self.correct/self.x*100)
Timestable.congrats.configure(text="Congrats, you got "+ str(data.percent) +"% of the questions correct",bg='#66bcb9')
self.x=0
for i in Timestable.incorrect:
Timestable.incdisplay.configure(state=NORMAL)
Timestable.incdisplay.insert(END,i)
Timestable.incdisplay.configure(state=DISABLED)
root = Tk()
root.geometry("300x300")
root.configure(bg='#66bcb9')
Timestable(root)
root.mainloop()

I cant update labels in tkinter

I can't seem to update my money counter(var money) when its labeled, I have a button that's supposed to add 0.1 to moneyNum but the money counter doesn't change. I'm new to stack overflow and would appreciate any help.(btw sry if its REALLY messy)
from tkinter import *
import random
from time import sleep
root = Tk()
root.geometry('320x320')
#spacing
spacingTitle = Label(root, text=" \n\n\n\n\n\n\n\n\n")
#title
title = Label(root, text=" \bGamblers Dream\b", font="Helvetica", fg="red")
titleWelcom = Label(root, text=" Welcom to...")
titleWelcom.grid()
title.grid()
#money counter
moneyNum = float(10.0)
money = Label(root, text="money:" + str(moneyNum), font="Helvetica")
money.grid(row=3, column=0)
#moneyClicker
def moneyButtonAdder():
global moneyNum
moneyNum = moneyNum + 0.1
moneyClicker = Button(root, text="click", fg="green", command=moneyButtonAdder)
moneyClicker.grid(row=14)
root.mainloop()
The problem is that once you create a label, you pass the string to it. Label displays the string, and:
changing a string object does not change the label text
changing the integer does not change the string - it lost the whole connection when the new string object was created
So everything is not as procedural as you would have hoped it is.
The solution - use StringVar objects and detect value changes - see this.
So, the solution is:
from tkinter import *
class Observed(object):
"""adapted copy from https://stackoverflow.com/a/6192298/10713244"""
def __init__(self):
self._observed = 10.0
self._observers = []
#property
def observed(self):
return self._observed
#observed.setter
def observed(self, value):
self._observed = value
for callback in self._observers:
print('announcing change')
callback(self._observed)
def bind_to(self, callback):
print('bound')
self._observers.append(callback)
class Observer(object):
def __init__(self, data):
self.text = ''
self.data = data
self.data.bind_to(self.update)
self.tkinter_init()
def update(self, observed):
self.text = 'float: '+str(data._observed)
self.tkinter_update()
def tkinter_init(self):
self.tk = Tk()
self.tvar = StringVar()
self.label = Label(textvariable=self.tvar)
self.label.pack()
def tkinter_update(self):
self.tvar.set(self.text)
if __name__ == '__main__':
data = Observed()
label = Observer(data)
print(label.text)
data.observed = 10.0
print(label.text)
def dec(): data.observed -= 0.1
Button(label.tk, text='decrease', command=dec).pack()
label.tk.mainloop()
Hope that's helpful!

How can I add a scrollbar to a frame containing a bunch of gridded buttons?

So I programmed a code which generates a window with a button on top and a small frame below. you click on the button on top and another button is created in col 0 row 0 in the small frame below, you click on it again and another button is created in col 0 row 1, so far so good that all works.
What I want to do now is to add a scrollbar such that, if the rows displayed in the small frame below become all filled with buttons, I can scroll down to the buttons added further down. The general question is thus: how can I add a scrollbar to a frame containing created buttons, organized via grid()?
I already tried to grid the created buttons in a frame, and to set that frame into a canvas, and then add the scrollbar onto that canvas, but nothing worked. (In the code below, take out the four lines of the scrollbar widget and you'll see how the program works. the addition of the four lines weirdly makes anything else disappear).
## import required modules ##
from tkinter import *
from functools import partial
## create window ##
window = Tk()
window.geometry("800x800")
## create global frame, which contains a canvas, which in turn contains ##
## the frame containing the grid of the products. This needs to be done ##
## in this way to be able to add a scrollbar aside the products grid ##
Globalframe = Frame(window, height = 210, width = 725)
Globalframe.place(relx = 0.03, rely = 0.54475)
Canv = Canvas(Globalframe, height = 198, width = 712)
Canv.place(relx = 0.00, rely = 0.01)
field = Frame(Canv, height = 186, width = 699)
field.place(relx = 0.00, rely = 0.01)
## add a scrollbar & configure it ##
scroll = Scrollbar(Globalframe, orient = VERTICAL)
scroll.config(command=Canv.yview)
Canv.config(yscrollcommand=scroll.set)
scroll.pack(side=RIGHT, fill=Y)
## create ADD button; function mentioned in command must be defined first ##
# predefine manufacturer variables & lists #
RIGOLVar = IntVar()
DataApexVar = IntVar()
DANIVar = IntVar()
Manufacturers = [["APPLE",RIGOLVar],["BANANA",DataApexVar],["PINEAPPLE",DANIVar]]
# predefine product variables & lists --> Put Lists into respective loops #
# because otherwise the system sends an unknown function error, which is #
# why the lists have been placed below the defined functions in the loop #
L31 = IntVar()
L32 = IntVar()
L34 = IntVar()
ListRIG=[["RED",L31],["GREEN",L32],["BROWN",L34]]
C801 = IntVar()
C82 = IntVar()
ListDAP =[["YELLOW",C801],["BROWN",C82]]
MS = IntVar()
HS = IntVar()
DHS = IntVar()
ListDAN=[["FRESH",MS],["INTERMEDIATE",HS],["OLD",DHS]]
# predefine amount variables & lists & directly sum it all up in one function (always the same) #
ONE = IntVar()
TWO = IntVar()
THREE = IntVar()
FOUR = IntVar()
FIVE = IntVar()
SIX = IntVar()
SEVEN = IntVar()
EIGHT = IntVar()
NINE = IntVar()
TEN = IntVar()
ELEVEN = IntVar()
TWELVE = IntVar()
THIRTEEN = IntVar()
FOURTEEN = IntVar()
FIFTEEN = IntVar()
SIXTEEN = IntVar()
SEVENTEEN = IntVar()
EIGHTEEN = IntVar()
NINETEEN = IntVar()
TWENTY = IntVar()
Varlist = [ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN,ELEVEN,TWELVE,THIRTEEN,FOURTEEN,FIFTEEN,SIXTEEN,SEVENTEEN,EIGHTEEN,NINETEEN,TWENTY]
Amlist = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
def detamount(Var):
for x in Varlist:
if x == Var:
x.set(1)
else:
x.set(0)
def OPAM(p):
a = StringVar()
for y in Merlist:
if y[1].get() == 1:
a = str(y[0])
else:
pass
for label in field.grid_slaves(row=p,column=6):
label.grid_forget()
mine = Label(field,text =a+"x",bg="cyan")
mine.grid(row=p, column = 6)
def F1(p):
detamount(ONE)
OPAM(p)
def F2(p):
detamount(TWO)
OPAM(p)
def F3(p):
detamount(THREE)
OPAM(p)
def F4(p):
detamount(FOUR)
OPAM(p)
def F5(p):
detamount(FIVE)
OPAM(p)
def F6(p):
detamount(SIX)
OPAM(p)
def F7(p):
detamount(SEVEN)
OPAM(p)
def F8(p):
detamount(EIGHT)
OPAM(p)
def F9(p):
detamount(NINE)
OPAM(p)
def F10(p):
detamount(TEN)
OPAM(p)
def F11(p):
detamount(ELEVEN)
OPAM(p)
def F12(p):
detamount(TWELVE)
OPAM(p)
def F13(p):
detamount(THIRTEEN)
OPAM(p)
def F14(p):
detamount(FOURTEEN)
OPAM(p)
def F15(p):
detamount(FIFTEEN)
OPAM(p)
def F16(p):
detamount(SIXTEEN)
OPAM(p)
def F17(p):
detamount(SEVENTEEN)
OPAM(p)
def F18(p):
detamount(EIGHTEEN)
OPAM(p)
def F19(p):
detamount(NINETEEN)
OPAM(p)
def F20(p):
detamount(TWENTY)
OPAM(p)
Famlist = [F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,F16,F17,F18,F19,F20]
Merlist = []
for i in range(20):
Merlist.append([Amlist[i],Varlist[i],Famlist[i]])
def askamount(p):
ab= Menubutton(field, text="Amount ?")
ab.menu = Menu(ab)
ab["menu"] = ab.menu
for i in Merlist:
ab.menu.add_checkbutton(label=i[0],variable = i[1],command=partial(i[2],p))
ab.grid(row=p, column = 5)
# function - Add Remove button, Manufacturer Label, & product dropdown menu #
# Define function to create product's output (functionalized because always same logic) #
def OPProd(li,co,p):
n = StringVar()
for s in li:
if s[1].get() == 1:
n = str(s[0])
else:
pass
for label in field.grid_slaves(row=r,column=co):
label.grid_forget()
mylab = Label(field,text=n,bg="green")
mylab.grid(row=p,column=co)
# Determine the picked Manufacturer and print the corresponding label to the right #
def setMANVar(V):
for b in Manufacturers:
if b[1] == V:
b[1].set(1)
else:
b[1].set(0)
def OPMAN(p):
c = StringVar()
for d in Manufacturers:
if d[1].get()==1:
c = str(d[0])
else:
pass
# Delete any previously created labels, to have the correct one for the end #
for label in field.grid_slaves(row=p,column=2):
label.grid_forget()
# Create the Label of the correct Manufacturer #
myl = Label(field,text=c,bg="green")
myl.grid(row=p,column=2)
# Create the next general checkbutton for the products #
pb = Menubutton(field,text = "Product ?")
pb.grid(row=p,column=3)
pb.menu = Menu(pb, tearoff=0)
pb["menu"] = pb.menu
# Create the dropdown-list of the product's button just created, in function of the picked manufacturer #
for label in field.grid_slaves(row=p,column=2):
if label["text"]=="APPLE":
def setRIGVar(Var):
for m in ListRIG:
if m[1] == Var:
m[1].set(1)
else:
m[1].set(0)
def FL31(p):
setRIGVar(L31)
OPProd(ListRIG,4,p)
askamount(p)
def FL32(p):
setRIGVar(L32)
OPProd(ListRIG,4,p)
askamount(p)
def FL34(p):
setRIGVar(L34)
OPProd(ListRIG,4,p)
askamount(p)
ListFRIG=[FL31,FL32,FL34]
for i in range(len(ListRIG)):
ListRIG[i].append(ListFRIG[i])
for i in ListRIG:
pb.menu.add_checkbutton(label=i[0],variable=i[1],command=partial(i[2],p))
elif label["text"]=="BANANA":
def setDAPVar(Var):
for m in ListDAP:
if m[1] == Var:
m[1].set(1)
else:
m[1].set(0)
def F801(p):
setDAPVar(C801)
OPProd(ListDAP,4,p)
askamount(p)
def F82(p):
setDAPVar(C82)
OPProd(ListDAP,4,p)
askamount(p)
ListFDAP=[F801,F82]
for i in range(len(ListDAP)):
ListDAP[i].append(ListFDAP[i])
for i in ListDAP:
pb.menu.add_checkbutton(label=i[0],variable=i[1],command=partial(i[2],p))
elif label["text"]=="PINEAPPLE":
def setDANVar(Var):
for m in ListDAN:
if m[1] == Var:
m[1].set(1)
else:
m[1].set(0)
def FMS(p):
setDANVar(MS)
OPProd(ListDAN,4,p)
askamount(p)
def FHS(p):
setDANVar(HS)
OPProd(ListDAN,4,p)
askamount(p)
def FDHS(p):
setDANVar(DHS)
OPProd(ListDAN,4,p)
askamount(p)
ListFDAN = [FMS,FHS,FDHS]
for i in range(len(ListDAN)):
ListDAN[i].append(ListFDAN[i])
for i in ListDAN:
pb.menu.add_checkbutton(label=i[0],variable=i[1],command=partial(i[2],p))
# Manufacturer Functions which set only the picked Manufacturer-Checkbutton = 1 and print the OP - Label #
def FRIG(p):
setMANVar(RIGOLVar)
OPMAN(p)
def FDAP(p):
setMANVar(DataApexVar)
OPMAN(p)
def FDAN(p):
setMANVar(DANIVar)
OPMAN(p)
## Define Clearline Function, associated to the remove button ##
def Clearline(p):
global num
for label in field.grid_slaves(row=p,column=0):
clickedbutton = label
for label in field.grid_slaves(row=p):
label.grid_forget()
remove_button_IDs.remove(clickedbutton)
for button in remove_button_IDs:
button.configure(text="- Remove Product #" + str(remove_button_IDs.index(button)+1))
num -= 1
## Create function associated to the ADD, starting up with the Remove and Manuf Button on a new row ##
r = -1
num = 0
remove_button_IDs = []
def AddProduct():
global r
global num
r += 1
num += 1
button = Button(field,text = "- Remove Product #" + str(num), bg = "red",command = partial(Clearline,r))
button.grid(row=r,column=0)
remove_button_IDs.append(button)
mb = Menubutton(field,text = "What ?")
mb.grid(row=r,column=1)
mb.menu = Menu(mb,tearoff=0)
mb["menu"] = mb.menu
ListFManufacturers = [FRIG,FDAP,FDAN]
for i in range(len(Manufacturers)):
Manufacturers[i].append(ListFManufacturers[i])
for i in Manufacturers:
mb.menu.add_checkbutton(label=i[0],variable=i[1],command= partial(i[2],r))
## Create ADD Button ##
A = Button(window, text = "+ Add a new product",command = AddProduct)
A.place(relx = 0.2, rely = 0.01)
correction from upon line 15:
def update_scrollregion(event):
Canv.configure(scrollregion=Canv.bbox("all"))
Globalframe = Frame(window, height = 210, width = 725)
Globalframe.place(relx = 0.03, rely = 0.54475)
Canv = Canvas(Globalframe, height = 198, width = 712)
Canv.grid(row=0,column=0,sticky="nsew")
field = Frame(Canv)
Canv.create_window(0,0,window=field,anchor="nw")
## add a scrollbar & configure it ##
s = Scrollbar(Globalframe, orient=VERTICAL)
s.config(command=Canv.yview)
Canv.config(yscrollcommand=s.set)
s.grid(row=0, column=1, sticky="ns")
field.bind("<Configure>",update_scrollregion)
I found this option thanks to j_4321 (Tkinter canvas & scrollbar with grid) GREAT THANKS TO THIS GUY!
See code from upon line 15 in my updated question; worked like that

How to make timer/program open only after pressing key instead of immediately?

I need to make this clock open only after pressing a key, lets say "t". Now it opens immediately after running it.
import tkinter as tk
def update_timeText():
if (state):
global timer
timer[2] += 1
if (timer[2] >= 100):
timer[2] = 0
timer[1] += 1
if (timer[1] >= 60):
timer[0] += 1
timer[1] = 0
timeString = pattern.format(timer[0], timer[1], timer[2])
timeText.configure(text=timeString)
root.after(10, update_timeText)
def start():
global state
state=True
state = False
root = tk.Tk()
root.wm_title('Simple Kitchen Timer Example')
timer = [0, 0, 0]
pattern = '{0:02d}:{1:02d}:{2:02d}'
timeText = tk.Label(root, text="00:00:00", font=("Helvetica", 50))
timeText.pack()
startButton = tk.Button(root, text='Start', command=start)
startButton.pack()
update_timeText()
root.mainloop()
It is in another program so as I have my graphics window I will press "t" and the clock will open.
Keyboard is a python module that can detect keystrokes. Install it by doing this command.
pip install keyboard
Now you can do this.
while True:
try:
if keyboard.is_pressed('t'):
state = True
elif(state != True):
pass
except:
state = False
break #a key other than t the loop will break
I would recommend you to organize the code little bit, like class structure. One possible implementation would be like that:
import tkinter as tk
TIMER = [0, 0, 0]
PATTERN = '{0:02d}:{1:02d}:{2:02d}'
class Timer:
def __init__(self, master):
#I init some variables
self.master = master
self.state = False
self.startButton = tk.Button(root, text='Start', command=lambda: self.start())
self.startButton.pack()
self.timeText = tk.Label(root, text="00:00:00", font=("Helvetica", 50))
self.timeText.pack()
def start(self):
self.state = True
self.update_timeText()
def update_timeText(self):
if (self.state):
global TIMER
TIMER[2] += 1
if (TIMER[2] >= 100):
TIMER[2] = 0
TIMER[1] += 1
if (TIMER[1] >= 60):
TIMER[0] += 1
TIMER[1] = 0
timeString = PATTERN.format(TIMER[0], TIMER[1], TIMER[2])
self.timeText.configure(text=timeString)
self.master.after(10, self.update_timeText)
if __name__ == '__main__':
root = tk.Tk()
root.geometry("900x600")
root.title("Simple Kitchen Timer Example")
graph_class_object = Timer(master=root)
root.mainloop()
So clock will start when you click to button. If you want to start the clock by pressing "t" in keyboard, you need to bind that key to your function.
You can also add functionality if you want to stop the clock when you click to the button one more time.
EDIT:
if you also want to start to display the clock by clicking the button, you can move the code for initializing the label in to start function.
def start(self):
self.state = True
self.timeText = tk.Label(root, text="00:00:00", font=("Helvetica", 50))
self.timeText.pack()
self.update_timeText()

How do I make the program wait for an input using an Entry box in Python GUI?

This is the code for the function I'm using to start the main part of the program, however I want some sort of loop or something which creates ten questions, but waits for an input from the Entry box before moving onto the next question.
Any ideas?
def StartGame():
root = Tk()
root.title("Maths Quiz - Trigonometry and Pythagoras' Theorem | Start The Game")
root.geometry("640x480")
root.configure(background = "gray92")
global AnswerEntry
TotScore = 0
Count = 0
AnswerReply = None
WorkingArea = Text(root, width = 70, height = 10, wrap = WORD).place(x = 38, y = 100)
n = GetRandomNumber()
Angle,Opposite,Adjacent,Hypotenuse = Triangle()
Question,RealAnswer = QuestionLibrary(Opposite,Adjacent,Hypotenuse,Angle,n)
AskQuestion = Label(root, text = Question, wraplength = 560).place(x = 48, y = 300)
PauseButton = ttk.Button(root, text = "Pause").place(x = 380, y = 10)
HelpButton = ttk.Button(root, text = "Help", command = helpbutton_click).place(x = 460, y = 10)
QuitButton = ttk.Button(root, text = "Quit", command = root.destroy).place(x = 540, y = 10)
AnswerEntry = Entry(root)
AnswerEntry.place(x = 252, y = 375)
SubmitButton = ttk.Button(root, text = "Submit", command = submit_answer).place(x = 276, y = 400)
TotScore,AnswerReply = IsAnswerCorrect(Answer,RealAnswer)
ScoreLabel = ttk.Label(root, text = TotScore).place(x = 38, y = 10)
AnswerReplyLabel = ttk.Label(root, text = AnswerReply).place(x = 295, y = 440)
root.mainloop()
I want the loop to start after the AnswerReply = None
You don't want a loop. The only really important loop inside a GUI should be the mainloop(), handling signal and executing callbacks.
Example:
try:
import Tkinter as Tk
except ImportError:
import tkinter as Tk
class QAGame(Tk.Tk):
def __init__(self, questions, answers, *args, **kwargs):
Tk.Tk.__init__(self, *args, **kwargs)
self.title("Questions and answers game")
self._setup_gui()
self._questions = questions[:]
self._answers = answers
self._show_next_question()
def _setup_gui(self):
self._label_value = Tk.StringVar()
self._label = Tk.Label(textvariable=self._label_value)
self._label.pack()
self._entry_value = Tk.StringVar()
self._entry = Tk.Entry(textvariable=self._entry_value)
self._entry.pack()
self._button = Tk.Button(text="Next", command=self._move_next)
self._button.pack()
def _show_next_question(self):
q = self._questions.pop(0)
self._label_value.set(str(q))
def _move_next(self):
self._read_answer()
if len(self._questions) > 0:
self._show_next_question()
self._entry_value.set("")
else:
self.quit()
self.destroy()
def _read_answer(self):
answer = self._entry_value.get()
self._answers.append(answer)
def _button_classification_callback(self, args, class_idx):
self._classification_callback(args, self._classes[class_idx])
self.classify_next_plot()
if __name__ == "__main__":
questions = ["How old are you?",
"What is your name?"]
answers = []
root = QAGame(questions, answers)
root.mainloop()
for q,a in zip(questions, answers):
print "%s\n>>> %s" % (q, a)
We only have a Label, an Entry and a Button (I did not care about layout!, just pack()).
Attached to the button is a command (aka callback). When the button is pressed, the answer is read and the new question is assigned to the label.
Usage of this class is understandable from the example in the `if name == "main" block. Please note: the answers-list is filled in place, the questions-list is kept unchanged.
I don't know Tk, but is there no any signals of input text changed? There should be for sure. Just check if this signal occured and then move onto new question, because it means that someone typed something in input box.

Categories

Resources