Twisted + PyGTK
Posted: February 27th, 2011 | Author: Martin Volpe | Filed under: Programming, PyGTK, Python, Twisted | Tags: asynchronous, gtk, pygtk, python, twisted | No Comments »A few weeks ago I starded interresting about Twisted and asynchronous programming. I realy liked the way that Twisted handles events and callbacks.
I’ve been working in a program with a graphical interface built in PyGTK that uses threads for every single taks and I wondered if I can had this program running in just one thread asynchronously. It’s realy simple implement twisted code in a PyGTK applicacion since both are event-based and Twisted has a native API to do so.
Let’s build a simple PyGTK example:
import gtk class Gui: def __init__(self): self.window = gtk.Window() self.window.set_default_size(200,200) self.window.set_title("Simple PyGTK program") self.vbox = gtk.VBox() self.button = gtk.Button("I'm a button!") self.label = gtk.Label("Nothing here") self.vbox.pack_start(self.button) self.vbox.pack_start(self.label) self.window.add(self.vbox) self.button.connect("clicked", self.on_clicked) self.window.connect("destroy", lambda x: gtk.main_quit()) self.window.show_all() self.window.show() def on_clicked(self, widget): self.label.set_text("You clicked the button!") if __name__ == "__main__": app = Gui() #starts the GTK loop gtk.main()
So, this example is using the Gtk loop. Twisted applications use the Twisted reactor, and we need the Twisted reactor to “understend” Gtk signals.
This is what you have to do:
from twisted.internet import gtk2reactor # for gtk-2.0 gtk2reactor.install() #Your code #... from twisted.internet import reactor #this starts the reactor reactor.run()
Now we can re-implement our first example and it would look like this:
import gtk from twisted.internet import gtk2reactor # for gtk-2.0 gtk2reactor.install() #this installs the gtk reactor #NOTE: This have to be at top always, before importing the reactor class Gui: def __init__(self): self.window = gtk.Window() self.window.set_default_size(200,200) self.window.set_title("Simple PyGTK program") self.vbox = gtk.VBox() self.button = gtk.Button("I'm a button!") self.label = gtk.Label("Nothing here") self.vbox.pack_start(self.button) self.vbox.pack_start(self.label) self.window.add(self.vbox) self.button.connect("clicked", self.on_clicked) self.window.connect("destroy", lambda x: gtk.main_quit()) self.window.show_all() self.window.show() def on_clicked(self, widget): self.label.set_text("You clicked the button!") if __name__ == "__main__": app = Gui() #No Gtk anymore! #gtk.main() from twisted.internet import reactor #let's start the loop reactor.run()
Now you can enjoy the Twisted power in your graphical apps, here is a (very)simple example using Twisted-way callbacks.
import gtk import time from twisted.internet import gtk2reactor # for gtk-2.0 gtk2reactor.install() #this installs the gtk reactor #NOTE: This have to be at top always, before starting the reactor class Gui: def __init__(self): self.window = gtk.Window() self.window.set_default_size(200,200) self.window.set_title("Simple PyGTK program") self.vbox = gtk.VBox() self.button = gtk.Button("I'm a button!") self.time = time.time() self.label = gtk.Label("0") self.vbox.pack_start(self.button) self.vbox.pack_start(self.label) self.window.add(self.vbox) self.button.connect("clicked", self.on_clicked) self.window.connect("destroy", lambda x: gtk.main_quit()) self.window.show_all() self.window.show() self.time = time.time() def on_clicked(self, widget=None): self.label_text = time.time() - self.time self.label.set_text("%.2fs" % self.label_text) #Twisted will call the sefl.on_clicked function every 100ms reactor.callLater(.1, self.on_clicked) if __name__ == "__main__": app = Gui() #No Gtk anymore! #gtk.main() from twisted.internet import reactor #let's start the loop reactor.run()
Twisted also has APIS for others toolkits such as Tkinter, wxPython, Win32(Windows) and PyUI.
For more information you can visit the official documentation.
