Time.sleep() not pausing the correct moment? - python

Hello I have created a quiz using python and tkinter. After each option is pressed I wanted the correct answer to turn green and the three incorrect to turn red then revert to the default for the next question.The problem here being that running the code will take the buttons to the default before the user can see the colours. To do this I tried to use time.sleep() in the function however no matter where I use it it just seems to pause on the button being pressed down and then goes onto the next question without seeing any colour change.
Here is the relevant piece of code
def entry(num):
global score
global x
global count
count +=1
if Qa[x] == 1:
option1.config(bg = "green")
option2.config(bg = "red")
option3.config(bg="red")
option4.config(bg="red")
elif Qa[x] == 2:
option1.config(bg="red")
option2.config(bg="green")
option3.config(bg="red")
option4.config(bg="red")
elif Qa[x] == 3:
option1.config(bg="red")
option2.config(bg="red")
option3.config(bg="green")
option4.config(bg="red")
elif Qa[x] == 4:
option1.config(bg="red")
option2.config(bg="red")
option3.config(bg="red")
option4.config(bg="green")
if num == Qa[x]:
score += 1
x +=1
if count <10:
my_label.config(text = Qs[x])
option1.config(text = (question_prompts[x])[1],bg = "SystemButtonFace",command = lambda: entry(1) )
option2.config(text=(question_prompts[x])[2],bg = "SystemButtonFace",command = lambda: entry(2) )
option3.config(text=(question_prompts[x])[3],bg = "SystemButtonFace",command = lambda: entry(3) )
option4.config(text=(question_prompts[x])[4],bg = "SystemButtonFace",command = lambda: entry(4) )
else:
End_score =Label(text = "Well done you scored" +" "+ str(score)+" " +"out of 11", font = 40)
End_score.place(relx=0.5,rely =0.5,anchor = CENTER)
print(x,score, count, Qa[x])
I haven't put the time.sleep() in here because I have tried it everywhere in this section an it gives the same result
I would really appreciate some help

The PROBLEM here is that the options will not actually change color until Tk can get back to its main loop. As long as you are running your function, the main loop cannot pull new events. You need to set the colors, then use root.after to schedule a callback at some point in the future where you reset to all green.

Related

How to go through while loop again?

Im making a simple question and answer app in python , in this specific example it displays a word in simple chinese and gives two answers to pick wrong or right , i'm struggling to present a new question without restarting my code. This my go at making an app that helps me learn chinese and I wanted to use minimum help , hence the weird code.
For example :
the question is what is 1+1 and the user answered two then I want to go thourgh the code again an present the next question.
the specific section im trying the run from inside a function, so when the user answers correctly or incorrectly by pressing the button in the function I want to go through the code again and present my next question
`
# ans
def button_1(event):
if Ans_option1.text == ans_or_not["ans"]:
print('correct')
return 'correct'
else:
print("incorrect")
def button_2 (event):
if Ans_option2.text == ans_or_not["ans"]:
print('correct')
return 'correct'
else:
print("incorrect")
Ans_option1 = gp.Button(app,return_1(), button_1)
Ans_option2 = gp.Button(app,return_2(),button_2)
app.add(Ans_option1,3,2, align = 'center')
app.add(Ans_option2,3,4, align = 'center')
app.run()
`
whole code
import gooeypie as gp
import random
app = gp.GooeyPieApp ('hello')
app.set_size (1000,500)
i = 2
n =3
while True :
# use dictionary instead of lists so we c an have an answer to the questions
question_dict = {
'xihuan' : 'like',
'Wo': 'I',
'Ni': 'you'
}
# random picks a value from a list of values made here
picker = random.choice(list(question_dict.values()))
# I remake the same list here again as the indexing stays the same then find the index for the random value
ind = list(question_dict.values()).index(picker)
# I make a list of the keys and they have mathing indexes to their values and we use the index number given to us previously to find the key
final = list(question_dict.keys())[ind]
# print(final)
test = 1
def question ():
question_dict.pop(final)
print(question_dict)
# return final
return final
ans_or_not = {
# this works first before the item is popped so it can cause a they same two words to appear on the buttons
# varialbe from inside the functions arent stected outside , making this whole dictionary meaningless
'ans' : picker,
'non' : random.choice(list(question_dict.values()))
}
print(ans_or_not["non"])
print(ans_or_not["ans"])
while ans_or_not["non"] == ans_or_not["ans"]:
ans_or_not.pop('non')
print(ans_or_not)
ans_or_not['non'] = random.choice(list(question_dict.values()))
print(ans_or_not["non"])
print(ans_or_not["ans"])
nums = random.randrange(1,3)
print(nums)
def return_1():
# while anss == nons :
# anss = random.randrange(0,2)
# print(anss + ','+ nons)
if nums == 1 :
return ans_or_not["ans"]
if nums == 2:
return ans_or_not["non"]
def return_2():
# while anss == nons :
# anss = random.randrange(0,2)
# print(anss + ','+ nons)
if nums == 1 :
return ans_or_not["non"]
elif nums == 2:
return ans_or_not["ans"]
# design and layout
def menu_select (event):
pass
menu_path = ' > '.join(event.menu)
status.text = menu_path
app.add_menu_item('Menu 1', 'Item 1', menu_select)
# grid setup
app.set_grid(4,5)
question_lbl = gp.Label(app,question())
app.add(question_lbl,2,3, align = 'center')
# ans
def button_1(event):
if Ans_option1.text == ans_or_not["ans"]:
print('correct')
return 'correct'
else:
print("incorrect")
def button_2 (event):
if Ans_option2.text == ans_or_not["ans"]:
print('correct')
return 'correct'
else:
print("incorrect")
Ans_option1 = gp.Button(app,return_1(), button_1)
Ans_option2 = gp.Button(app,return_2(),button_2)
app.add(Ans_option1,3,2, align = 'center')
app.add(Ans_option2,3,4, align = 'center')
app.run()
What i've tried
i've tried using the continue function
ways to restart while loops
You have the problem wrong.
This is going to sound really complicated, but stay with me. So what app.run() does is start the program, and it displays what you have already added to it. By putting app.run() in the while loop, despite calling it multiple times, will only call once. What you need to do is draw the label and buttons, run the app, then start the while loop. In fact, I wouldn't use a while loop here at all. Instead, I would have is so you have a dictionary for the right and wrong answers, then simply modify that and the button text when you get the answer correct. I don't really understand your code, but it would look something like:
#function for choosing answer
#function for checking button one
#function for checking button two
#draw button one and two and label
app.run()
Also, you would have it so that if you got the answer right, you would choose a new one.

Pause a for loop to wait for a button press

I am trying to build an image classifier and I need to manually assign classifications for a training dataset, so I build a file browser /media window app in tkinter to display images and assign them classifications via a button click. To iterate over the files, I am using a for loop, but I need it to pause and wait for that input. Here is my code:
def setKnownData(self):
training_sample = self.dataset.sample(frac = .1)
print(training_sample)
for i, row in training_sample.iterrows():
print(row)
global img
file = Image.open(row['ID'])
resized = file.resize((500,600))
img = ImageTk.PhotoImage(resized)
self.media_window.create_image(0,0, anchor = 'nw', image = img)
self.event_var.get()
while True:
if self.event_var.get() == 0:
print(self.event_var.get())
return
if self.event_var.get() == 1:
training_sample.loc[row]['class'] = 'cartoon'
break
elif self.event_var.get() ==2:
training_sample.loc[row]['class'] = 'photo'
break
self.event_var.set(0)
def stateSwitch(self, action):
print('state switching....')
if action == 'toon':
print(self.event_var.get())
self.event_var.set(1)
print('classification: TOON', self.event_var.get())
elif action == 'photo':
self.event_var.set(2)
print('classification: PHOTO')
I've exausted every combination of IntVar, tkinter, and for loop searches and can't find a viable solution, so I apologize if this is a repeat question. How can I pause this for loop, wait for a putton press, and then proceed to the next image in the list?
You need to shift your thinking away from pausing the loop. That's procedural programming, but GUIs are work much better as "event driven programming", where the entire program is just endlessly waiting for an event (like a button press) to happen. The means no loops, besides the tkinter mainloop. And it means making a new function for every event.
def setKnownData(self):
training_sample = self.dataset.sample(frac = .1)
print(training_sample)
self.training_sample = training_sample.iterrows()
def on_button_click(self):
i, row = next(self.training_sample)
print(row)
global img
file = Image.open(row['ID'])
resized = file.resize((500,600))
img = ImageTk.PhotoImage(resized)
self.media_window.create_image(0,0, anchor = 'nw', image = img)
self.event_var.get()
while True:
if self.event_var.get() == 0:
print(self.event_var.get())
return
if self.event_var.get() == 1:
training_sample.loc[row]['class'] = 'cartoon'
break
elif self.event_var.get() ==2:
training_sample.loc[row]['class'] = 'photo'
break
self.event_var.set(0)

How to stay in while loop, but pausing to receive new button input

I'm new at programming and I cant seem to figure out how to make "konto" keep updating without it being in a while loop. Problem with the while loop is it doesn't allow new button input because it freezes the window.
I've tried making "konto" local, splitting the code into different functions, changing the loop style. Break exits the loop so "konto" doesn't update.
konto = 100
roulette_window = Tk()
def roulette(chosen_color, sats, konto):
while True:
x = randint(0, 36)
if x == 0:
green_num = x
print(green_num, 'Green')
color = ('Green')
if color and chosen_color == 'Green':
win_amount = 35 * int(sats)
elif (x % 2) == 0:
red_num = x
print(red_num, 'Red')
color = ('Red')
if color and chosen_color == 'Red':
win_amount = 2 * int(sats)
elif (x % 2) == 1:
black_num = x
color = ('Black')
print(black_num, 'Black')
if color and chosen_color == 'Black':
win_amount = 2 * int(sats)
if not color == chosen_color:
win_amount = 0
konto = konto - int(sats) + int(win_amount)
print(konto)
def bet_black():
sats = bet_input.get(1.0, END)
chosen_color = 'Black'
bet_input.delete(1.0, END)
roulette(chosen_color, sats, konto)
def bet_red():
I want to be able to call the function "roulette" once by eg. bet_black button click, and then click bet_red after one loop, while still having the updated "konto" variable.
Firstly your variable konto is a global variable and you need to indicate to python that it is. Change your method to:
def roulette(chosen_color, sats):
global konto
...
Variables in Python have scoping rules which determine where they are valid. Anytime you assign to a variable a local version of the variable is created unless you have explicitly marked it as a global variable.
Secondly, I'm not sure why you have the while True structure here. This will cause an infinite loop unless you break out of it or return.

Is there anyway I can make an if statement about an led on a button-shim being a certain color?

I am currently making a burglar alarm for a school project. I am trying to make a button that will disable the alarm when pressed. I originally thought to have a variable change when the button shim is pressed but, while the rest of the activities in the if loop happen, the variable is not being changed.
My code looks like this:
while (check1 == 0):
if (bE == 0): #if button E has not been pressed
if (check() = 1): # a function that returns if there is moton
check1 = 1
#buttonshim.on_press(buttonshim.BUTTON_E)
def button_e(button, pressed):
buttonshim.set_pixel(0xff, 0x00, 0x00) #changes led to red no prob
bE = 1 #supposed to change variable to 1 not working
print "button e pressed" #prints out fine
time.sleep(sleeptime) #so it's not checking constantly
else:
check1=1 #so it breaks out of while loop is E is pressed
I had already defined check1 and bE as variables before this code segment.
This is not working properly and I was wondering if there is any way that I can detect if the led is red so I can make an if statement and set the variable through that?
The syntax error in your first line might be the issue. Same with your if .statements
while (check1 = 0): #should be while (check1 == 0):
# rest of the code

Command function for button "resets"

So in my tkinter python program I am calling on a command when a button is clicked. When that happens it runs a function but in the function I have it set a label to something on the first time the button is clicked and after that it should only update the said label. Basically after the attempt it changes the attempt to 1 ensuring the if statement will see that and not allow it to pass. However it keeps resetting and I don't know how to stop it. When you click the button no matter first or third the button resets and proof of that occurs because the h gets printed. It's as if the function restarts but it shouldn't since it's a loop for the GUI.
def fight(): #Sees which one is stronger if user is stronger he gets win if no he gets loss also displays enemy stats and removes used characters after round is finished
try:
attempt=0
namel = ""
namer=""
left = lbox.curselection()[0]
right = rbox.curselection()[0]
totalleft = 0
totalright = 0
if left == 0:
namel = "Rash"
totalleft = Rash.total
elif left==1:
namel = "Untss"
totalleft = Untss.total
elif left==2:
namel = "Illora"
totalleft = 60+35+80
if right == 0:
namer = "Zys"
totalright = Zys.total
elif right==1:
namer = "Eentha"
totalright = Eentha.total
elif right==2:
namer = "Dant"
totalright = Dant.total
lbox.delete(lbox.curselection()[0])
rbox.delete(rbox.curselection()[0])
print(namel)
print(namer)
if attempt == 0:
wins.set("Wins")
loss.set("Loss")
print("h")
attempt=1
if (totalleft>totalright):
wins.set(wins.get()+"\n"+namel)
loss.set(loss.get()+"\n"+namer)
else:
wins.set(wins.get()+"\n"+namer)
loss.set(loss.get()+"\n"+namel)
except IndexError:
pass
Also for those of you who saw my previous question I still need help with that I just also want to fix this bug too.
At beginning of function fight you set attempt = 0 so you reset it.
Besides attempt is local variable. It is created when you execute function fight and it is deleted when you leave function fight. You have to use global variable (or global IntVar)
attempt = 0
def fight():
global attempt
BTW: of you use only values 0/1 in attempt then you can use True/False.
attempt = False
def fight():
global attempt
...
if not attempt:
attempt = True

Categories