2010-06-03 49 views
2

我有一個用Glade創建的界面。它包含一個DrawingArea和按鈕。如何刷新PyGTK中的DrawingArea?

我試圖創建一個線程來刷新每X時間我的Canva。幾秒鐘後,我得到錯誤信息,如:

「X Window服務器0.0」, 「致命錯誤IO 11」

這裏是我的代碼:

import pygtk 
pygtk.require("2.0") 
import gtk 
import Canvas 
import threading as T 
import time 
import Map 

gtk.gdk.threads_init() 

class Interface(object): 
    class ThreadCanvas(T.Thread): 
     """Thread to display the map""" 
     def __init__(self, interface): 
      T.Thread.__init__(self) 
      self.interface = interface 
      self.started = True 
      self.start() 

     def run(self): 
      while self.started: 
       time.sleep(2) 
       self.interface.on_canvas_expose_event() 

     def stop(self): 
      self.started = False 

    def __init__(self): 
     self.interface = gtk.Builder() 
     self.interface.add_from_file("interface.glade") 

    #Map 
    self.map = Map.Map(2,2) 

     #Canva 
     self.canvas = Canvas.MyCanvas(self.interface.get_object("canvas"),self.game) 
     self.interface.connect_signals(self) 

     #Thread Canvas 
     self.render = self.ThreadCanvas(self) 

    def on_btnChange_clicked(self, widget): 
    #Change map 
     self.map.change() 

    def on_interface_destroy(self, widget): 
     self.render.stop() 
     self.render.join() 
     self.render._Thread__stop() 
     gtk.main_quit() 

    def on_canvas_expose_event(self): 
     st = time.time() 
     self.canvas.update(self.map) 
     et = time.time() 
     print "Canvas refresh in : %f times" %(et-st) 

    def main(self): 
     gtk.main() 

我怎樣才能解決這些錯誤?

回答

1

要在PyGTK中使用Python線程,您需要圍繞對共享GTK對象的任何訪問,其中包括gtk.gdk.threads_enter()gtk.gdk.threads_leave()。另請參閱threads_enter()方法。 (請注意,最近這些函數稍微移動了一下,在您的安裝中它們可能位於GObject而不是GLib)。您可能更適合使用GTKs函數進行定期函數調用,例如timeout_add(...)timeout_add_seconds(...)

其他一些注意事項:

  1. 子類Thread對象是做事,而不是Python的方式Java的方式。 Python的方法是定義一個你需要的函數或可調用對象,並將它傳遞給一個Thread構造函數。您可能不會使用_Thread__stop()。它的名字因爲一個原因而被破壞,它構成了Thread對象的內部機制的一部分,並且不適合公共使用。相反,您應該使用其中一個線程安全對象(例如,一個Condition對象),並在第一步中將其傳遞給線程對象的函數中進行檢查。或者,將線程設置爲守護進程,以便程序退出時自動關閉。
  2. 常用的擴展GTKBuilder文件是「的.ui」,而不是「.glade」(即使格萊德本身追加「.glade」作爲默認的擴展名。)

我希望這有助於。

+0

謝謝,它的工作原理。我試圖使用Thread.Lock()和Thread.RLock()來進行任何訪問。 我注意到你的意見。 – Lialon 2010-06-03 11:13:13