2017-04-02 68 views
1

我想实现一个应用程序来显示图像6秒,然后跳转到另一个页面与单选按钮,让他们评价他们自己对图像的感觉(15给评级),然后显示下一张图片。但是,为了倒数15秒,我使用了time.sleep()函数,这使得按下单选按钮的程序非常缓慢(但是我的点击,按钮仍然可以按下)。我想知道是否有减少倒数不会影响程序的方法,但只要让程序在时间到达时跳到下一页。这里是我的代码:time.sleep块按tkinter.Button

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

不要在tkinter中使用time.sleep,它只会让程序不响应。 – abccd

+0

我应该使用多线程吗?任何细节apprieciated。 –

回答

1

tkinter程序使用time.sleep()会使其反应迟钝,因为它使mainloop()从执行,并能够对事件做出响应。

若要使用通用小部件方法after()无效。

所以,你的情况使用:的

self.after(1000) # 1000 ms = 1 sec 

代替

time.sleep(1) 

下面是一些documentation我发现它。

+0

非常感谢!它会继续慢下来,没有倒计时的按钮?因为我仍然需要点击几次才能得到回复。 –

+0

它确实将事情延迟了一秒钟,每次它被调用 - 所以答案可能是“是”。尝试点击**一次**,等待一秒钟,以回应证明这一点。 – martineau

+0

你也可以使用'after()'来安排一个函数在给定的延迟后被调用。这可能是一个更好的方法来获得你以后的效果。 – martineau