我正在尝试实现一个应用程序以显示6s的图像,然后跳转到另一个带有单选按钮的页面,让他们评估自己对图像的感觉(给15秒评级),然后显示下一个图像。然而,为了倒计时15秒,我使用了time.sleep()函数,这使得程序在按下radiobuttons时非常慢(但是我的点击,仍然可以按下按钮)。我想知道是否有一种方法,倒计时不会影响程序,只是让程序在时间到时跳转到下一页。这是我的代码:
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()
答案 0 :(得分:2)
在time.sleep()
程序中使用tkinter
会使其无法响应,因为它会使mainloop()
无法执行并能够响应事件。
使用通用窗口小部件方法after()
无效。
因此,在您的情况下使用:
self.after(1000) # 1000 ms = 1 sec
而不是
time.sleep(1)
我发现了一些documentation。