如何刷新PyGTK中的DrawingArea?

时间:2010-06-03 05:50:13

标签: python multithreading drawing pygtk

我有一个用Glade创建的界面。它包含一个DrawingArea和按钮。

我尝试创建一个Thread来刷新我的Canva每X次。几秒钟后,我收到如下错误消息:

“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 个答案:

答案 0 :(得分:1)

要在PyGTK中使用Python线程,您需要使用gtk.gdk.threads_enter()gtk.gdk.threads_leave()包围对共享GTK对象的任何访问。另请参阅threads_enter()方法。

你甚至可以更好地使用GTK函数进行周期性函数调用,例如timeout_add(...)timeout_add_seconds(...)(请注意,最近这些函数移动了一下,在安装中它们可能在GObject中而不是GLib)。

其他一些说明:

  1. 子类化Thread对象是Java的处理方式,而不是Python方式。 Python的方法是定义一个函数或可调用对象,你需要它并将它传递给一个Thread构造函数。
  2. 您不应该使用_Thread__stop()。由于某种原因,它的名称被破坏,因为它构成了Thread对象内部机制的一部分,不适合正常的公共使用。相反,您应该使用其中一个线程安全对象(例如,一个Condition对象),并从您在第一步中传递给Thread对象的函数中检查它。或者,将Thread设置为守护进程,因此当程序退出时它将自动死亡。
  3. GTKBuilder文件的通常扩展名为“.ui”,而不是“.glade”(即使Glade本身附加“.glade”作为默认扩展名。)
  4. 我希望这会有所帮助。