如何在PyGTK中刷新DrawingArea?
我用Glade创建了一个界面,里面有一个绘图区域和一些按钮。
我尝试创建一个线程,让我的画布每隔一段时间刷新一次。但是过了几秒钟,我就收到了错误信息,比如:
“X Window Server 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 个回答
1
在PyGTK中使用Python线程时,你需要在访问共享的GTK对象时,使用 gtk.gdk.threads_enter() 和 gtk.gdk.threads_leave() 来包裹这些操作。你也可以看看 threads_enter() 方法。
其实,使用GTK提供的定时调用函数可能更好,比如 timeout_add(...) 和 timeout_add_seconds(...) (注意,这些函数最近有些位置变动,可能在你的安装中它们在GObject而不是GLib里)。
还有一些其他的注意事项:
- 在Python中,不建议像Java那样去子类化Thread对象。Python的做法是定义一个函数或可调用对象,然后把它传给Thread构造函数。
- 不要使用
_Thread__stop()
。这个名字被处理过是有原因的,它是Thread对象内部机制的一部分,不是给普通用户使用的。你应该使用一些线程安全的对象(比如 Condition 对象),并在你传给Thread对象的函数中检查它。或者,你可以把你的Thread设置为守护线程,这样当程序退出时它会自动结束。 - GTKBuilder文件的常用扩展名是“.ui”,而不是“.glade”(尽管Glade本身默认会加上“.glade”作为扩展名)。
希望这些信息对你有帮助。