[英]time.sleep blocks pressing tkinter.Button
I am trying to implement an app to show image for 6s and then jump to another page with radio buttons to let them rate their own feeling about the images (give 15s for rating) and then show the next image. 我正在尝试实现一个应用程序,以显示6s的图像,然后跳转到带有单选按钮的另一页,以让他们对图像的感觉进行评分(给15s评分),然后显示下一张图像。 However, for counting down 15s, I used time.sleep() function, which make the program very slow for pressing radiobuttons (but my clicking, the button can still be pressed). 但是,为了倒数15秒,我使用了time.sleep()函数,该函数使按下单选按钮的程序非常慢(但是单击后仍可以按下该按钮)。 I am wondering whether there is a way that the count down will not influence the program but just let the program jump to the next page when time up. 我想知道是否有一种方法,倒数不会影响程序,而只是在时间到时让程序跳到下一页。 Here is my code : 这是我的代码:
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.geometry('1800x970+15+5')
self.title('Emotion Test')
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
container = tk.Frame(self)
container.pack(side="top", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, Show_image, Rate_e, EndPage):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
frame.execute()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text=instructions, width=1500, height=700, font=TITLE_FONT)
label.pack(side="top")
label.place(x=100, y=40, width=1500, height=700)
button1 = tk.Button(self, text="Start", height = 5, width = 10,
command=lambda: controller.show_frame("Show_image"))
button1.pack(side="bottom")
def execute(self):
current = -1
class EndPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text=instructions, width=1500, height=700,
font=TITLE_FONT)
label.pack(side="top")
label.place(x=100, y=40, width=1500, height=700)
def execute(self):
current = -1
class Show_image(tk.Frame):
def __init__(self, parent, controller):
global seconds
tk.Frame.__init__(self, parent)
self.controller = controller
global lbPic
global timer1
lbPic = tk.Label(self, text='Image System', width=1200, height=900)
lbPic.place(x=20, y=50, width=1200, height=900)
lbPic.pack(side="top", fill="both", expand=True)
timer1 = tk.Label(self, text='timer', width=50, height=10)
timer1.place(x=1325, y=2, width=50, height=10)
timer1.pack(side="bottom", fill="both", expand=True)
def execute(self):
if (self.changePic(1)):
for k in range(seconds, 0, -1):
timer1["text"] = "Time left : " + str(k) + " s"
self.update()
time.sleep(1)
self.controller.show_frame("Rate_e")
else:
self.controller.show_frame("EndPage")
def changePic(self, flag):
global current
new = current + flag
if new<0:
#tkMessageBox.showerror('', 'last picture')
return 0
elif new>=len(pics):
#tkMessageBox.showerror('', 'last picture')
return 0
else:
#get the next picture
pic = pics[new]
im = Image.open(pic)
w, h = im.size
if w>1200:
h = int(h*1200/w)
w = 1200
if h>800:
w = int(w*800/h)
h = 800
im = im.resize((w,h))
im1 = ImageTk.PhotoImage(im)
lbPic['image'] = im1
lbPic.image = im1
current = new
return 1
class Rate_e(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
global wait
self.controller = controller
global lbrate1
global lbrate2
global lbrate3
global timer2
lbrate1 = tk.Label(self, text='Pleasure', width=1400, height=260)
lbrate1.place(x=50, y=10, width=1400, height=260)
lbrate1.pack(side="top", fill="both", expand=True)
lbrate2 = tk.Label(self, text='Excited', width=1400, height=260)
lbrate2.place(x=50, y=230, width=1400, height=260)
lbrate2.pack(side="top", fill="both", expand=True)
lbrate3 = tk.Label(self, text='Controlled', width=1400, height=260)
lbrate3.place(x=50, y=650, width=1400, height=260)
lbrate3.pack(side="top", fill="both", expand=True)
timer2 = tk.Label(self, text='timer', width=50, height=10)
timer2.place(x=800, y=850, width=50, height=10)
timer2.pack(side="bottom", fill="both", expand=True)
MODES = [
("1", 1),
("2", 2),
("3", 3),
("4", 4),
("5", 5),
("6", 6),
("7", 7),
("8", 8),
("9", 9)
]
global v1
v1 = tk.StringVar()
v1.set("score1") # initialize
xaxis = 0
for text, mode in MODES:
b1 = tk.Radiobutton(self, text=text,
variable=v1, value=mode)
b1.config(indicatoron=False,width=10,height=2)
b1.place(x=140 + xaxis*127, y=240 , width=100, height=30)
#b.pack(side="left")
xaxis = xaxis + 1
global v2
v2 = tk.StringVar()
v2.set("score2") # initialize
xaxis = 0
for text, mode in MODES:
b2 = tk.Radiobutton(self, text=text,
variable=v2, value=mode)
b2.config(indicatoron=False,width=10,height=2)
b2.place(x=140 + xaxis*128, y=510 , width=100, height=30)
#b.pack(side="left")
xaxis = xaxis + 1
global v3
v3 = tk.StringVar()
v3.set("score3") # initialize
xaxis = 0
for text, mode in MODES:
b3 = tk.Radiobutton(self, text=text,
variable=v3, value=mode)
b3.config(indicatoron=False,width=10,height=2)
b3.place(x=140 + xaxis*125, y=800 , width=100, height=30)
#b.pack(side="left")
xaxis = xaxis + 1
def execute(self):
for k in range(wait, 0, -1):
timer2["text"] = "Time left : " + str(k) + " s"
self.update()
time.sleep(1)
Pleasure = v1.get()
Excited = v2.get()
Control = v3.get()
print(Pleasure)
print(Excited)
print(Control)
self.controller.show_frame("Show_image")
if __name__ == "__main__":
suffix = ('.jpg', '.bmp', '.png')
pics = [image_path + p for p in os.listdir(image_path) if p.endswith(suffix)]
seconds = 2
wait = 6
current = -1
app = SampleApp()
app.mainloop()
Using time.sleep()
in a tkinter
program will make it unresponsive since it keeps the mainloop()
from executing and able to respond to events. 使用time.sleep()
在tkinter
,因为它使该方案将使其反应迟钝mainloop()
从执行,并能够对事件做出响应。
To void that use the universal widget method after()
. 要使此无效,请使用after()
通用小部件方法。
So, in your case use: 因此,在您的情况下使用:
self.after(1000) # 1000 ms = 1 sec
instead of 代替
time.sleep(1)
Here's some documentation I found about it. 这是我发现的一些文档 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.