views:

195

answers:

1

I have an interface created with Glade. It contains a DrawingArea and buttons.

I tried to create a Thread to refresh every X time my Canva. After a few seconds, I get error messages like:

"X Window Server 0.0", "Fatal Error IO 11"

Here is my code :

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()

How can i fix these errors ?

+1  A: 

To use Python threads in PyGTK, you need to surround any access to shared GTK objects with gtk.gdk.threads_enter() and gtk.gdk.threads_leave(). See also the threads_enter() method.

You might even be better off using GTKs functions for periodic function calls, such as timeout_add(...) and timeout_add_seconds(...) (note that recently these functions moved around a bit, and in your installation they might be in GObject and not GLib).

Some other notes:

  1. Subclassing Thread objects is the Java way of doing things, not the Python way. The Python way is to define a function or callable object that what you need and pass it to a Thread constructor.
  2. You should not be using _Thread__stop(). It is name mangled for a reason, which is that it forms part of the internal mechanism of the Thread object and is not for normal public use. Instead, you should use one of the thread-safe objects (eg. a Condition object) and check it from the function you passed to your Thread object in step one. Alternatively, set your Thread as a daemon, so it will automatically die when the program exits.
  3. The usual extension for GTKBuilder files is ".ui", not ".glade" (even though Glade itself appends ".glade" as the default extension.)

I hope this helps.

detly
Thanks, it works. I tried to use Thread.Lock() and Thread.RLock() to surrond any access.I take note of yours comments.
Lialon