Search code examples
pythonmultithreadinggtkraspberry-pigdk

'gi.repository.Gtk' object has no attribute 'gdk'


I'm trying to create a multiple threading with GTK. Gtk.gdk is needed but i received error about no gdk attribute. I'm using a Raspberry Pi with Raspbian.

This is how i import GTK library.

try:  
    import pygtk
    pygtk.require("2.0")  
except:  
    pass  

try:  
    from gi.repository import Gtk
except:  
    print("GTK Not Available")
    sys.exit(1)

Gtk.gdk.threads_init()

and this is the error i received.

AttributeError'gi.repository.Gtk' object has no attribute 'gdk'

Any idea?

Updates : I'm following this tutorial http://faq.pygtk.org/index.py?req=show&file=faq14.023.htp which are using both GObject.threads_init() & Gtk.gdk.threads_init(). I have no problem using GObject but gdk.


Solution

  • I think the equivalent of the old-style gtk.gdk.threads_init() is:

    from gi.repository import Gdk
    Gdk.threads_init()
    

    However, as the FAQ warns, threading is not a clean way to achieve this goal. A much better way is to use GObject.idle_add to run a function whenever the GUI is idle.


    """Show a shell command's output in a gtk.TextView without freezing the UI"""
    
    import os
    import locale
    import subprocess
    import shlex
    import gi.repository.Gtk as gtk
    from gi.repository import GObject
    PIPE = subprocess.PIPE
    
    encoding = locale.getpreferredencoding()
    
    
    def utf8conv(x):
        return unicode(x, encoding).encode('utf8')
    
    
    class MyWindow:
        def __init__(self):
            sw = gtk.ScrolledWindow()
            sw.set_policy(gtk.PolicyType.AUTOMATIC, gtk.PolicyType.AUTOMATIC)
            textview = gtk.TextView()
            textbuffer = textview.get_buffer()
            sw.add(textview)
            win = gtk.Window()
            win.resize(300, 500)
            win.connect('delete-event', gtk.main_quit)
    
            self.button_sim = gtk.Button(u"Press me!")
            self.button_abort = gtk.Button("Abort")
            self.button_quit = gtk.Button("Quit")
    
            command = 'ls -R %s' % (os.getcwd(),)
            self.button_sim.connect(
                "clicked", self.on_button_clicked, textview, textbuffer, command)
            self.button_abort.connect("clicked", self.on_abort)
            self.button_quit.connect("clicked", self.main_quit)
    
            vbox = gtk.VBox()
            vbox.pack_start(self.button_sim, expand=False, fill=False, padding=0)
            vbox.pack_start(self.button_abort, expand=False, fill=False, padding=0)
            vbox.pack_start(self.button_quit, expand=False, fill=False, padding=0)
            vbox.pack_start(sw, expand=True, fill=True, padding=0)
            win.add(vbox)
            win.show_all()
    
        def read_output(self, view, buffer, command):
            yield True  # allow the UI to refresh
            proc = subprocess.Popen(
                shlex.split(command), stderr=PIPE, stdout=PIPE)
            while True:
                if self.job_aborted:
                    print('user aborted')
                    proc.terminate()
                    break
    
                try:
                    line = proc.stdout.readline()
                    if line:
                        it = buffer.get_end_iter()
                        buffer.place_cursor(it)
                        buffer.insert(it, utf8conv(line))
                        view.scroll_to_mark(buffer.get_insert(), 0.1,
                                            use_align=False, xalign=0.5, yalign=0.5)
    
                except IOError:
                    pass
    
                yield True
    
            yield False
    
        def on_button_clicked(self, button, view, buffer, command):
            self.job_aborted = False
            GObject.idle_add(self.read_output(view, buffer, command).next)
    
        def on_abort(self, button):
            self.job_aborted = True
    
        def main_quit(self, obj):
            self.job_aborted = True
            gtk.main_quit()
    
    
    if __name__ == "__main__":
        app = MyWindow()
        gtk.main()