2011-06-08 45 views
1

我是一名高中程序設計專業的學生,​​我有一個小問題。我一直負責在Tkinter編寫一個簡單的遊戲,在那裏冰柱從天花板上掉下來,你必須用鼠標避免它。夠簡單。但是,我遇到了一個問題。每當我在Tkinter應用程序中運行循環時,它都不會打開。我已經嘗試過使用time.sleep()每隔0.5秒暫停一次的for循環,只要循環結束,窗口就會打開。我需要做些什麼特殊的事情來讓循環在Tkinter中工作?沿着Tkinter應用程序運行一個循環

from Tkinter import * 
import time 
import random 

class App: 
    def __init__(self, parent): 
     self.frame = Frame(root, bg= '#1987DF', width=800, height=800) 
     self.frame.bind("<Motion>", self.motionevent) 
     self.frame.pack() 
     #self.run() 
    def randhex(self): 
     b = "#" 
     for i in range(1, 7): 
      a = random.randint(0, 15) 
      if a == 10: 
       a = "A" 
      elif a == 11: 
       a = "B" 
      elif a == 12: 
       a = "C" 
      elif a == 13: 
       a = "D" 
      elif a == 14: 
       a = "E" 
      elif a == 15: 
       a = "F" 
      b = b+str(a) 
     return b 

    def motionevent(self, event): 
     xpos, ypos, bg = event.x, event.y, self.randhex() 
     str1 = "X : %d Y : %d BG : %s" % (xpos, ypos, bg) 
     root.title(str1) 
     x,y, delta = 100, 100, 10 
     self.frame.config(bg=bg) 

    def run(self): 
     for i in range(0, 10): 
      time.sleep(.5) 
      print 'i' 
      self.frame.config(bg=self.randhex()) 

root = Tk() 
app = App(root) 
root.mainloop() 

目前它所要做的就是在鼠標移動時更改背景。當init中的行表示self.run()未註釋時,它將打印'i'10次,然後窗口打開。幫幫我?

+0

可能是回答:http://stackoverflow.com/questions/459083/how-do-you-run-your-own-code-alongside-tkinters-event-loop – schlenk 2011-06-08 20:17:52

回答

5

編寫基於事件的程序與編寫傳統程序不同。已經有一個無限循環運行,並且像任何無限循環一樣,如果將另一個循環放入其中,則外循環無法繼續,直到內循環結束。由於外層循環是導致屏幕刷新並處理事件的原因,因此內層循環會有效地凍結您的應用,直到完成爲止。

由於已經有一個循環運行,所以不需要創建另一個循環。您只需要逐個添加一些作業到事件隊列中。實際上,每個工作都是內部循環的一次迭代。

例如,如果你想寫一個內部循環是這樣的:

for i in range(10): 
    print "i:", i 

...你不是一個事件的事件循環迭代(或者更精確地添加到事件隊列和每一次,每次它完成處理任何其他事件時)它將執行循環的一次迭代。你不喜歡這樣:

def do_one_iteration(i): 
    print "i:", i 
    if i < 9: 
     root.after_idle(do_one_iteration, i+1) 

然後,你第一次調用do_one_iteration後,它將把自身對事件隊列中的下一個迭代,並繼續這樣做,直到它決定它完成。

通常,當用戶按下按鈕(例如:「開始」按鈕)時,您會撥打do_one_iteration。調用它一次,然後它完成一項工作(即:將冰柱向下移動幾個像素),然後重新安排自己。

在遊戲開發中,您可能會有一個名爲update_display的函數負責重繪所有內容。例如,它可以從每個冰柱的Y座標中減去1。您可以添加左右箭頭的綁定來移動播放器(通過遞增或遞減X座標),並且您的更新函數將使用這些新座標來重繪播放器。

順便說一下,您可以通過使用after而不是after_idle稍微延遲後調用該函數來減慢程序運行速度。這個延遲可以用來控制幀速率。例如,假設更新幾乎是瞬時的(並且可能是您的情況),使用41(毫秒)的參數調用after會產生大約24 fps的幀率(24幀時間41毫秒等於984毫秒或大約24幀每秒)

這聽起來很複雜,但實際上一旦你做了一次或兩次真的很容易。