Search posterous

Search all posts and users. Type a name, type a favorite song title, whatever! See what comes up.
  

More posterous blogs











More recommended blogs »

Here are posterous posts filed under gtk...

A fast post about how to install RuGUI on Ubuntu 9.04.

  • Installing Ruby and libs.

sudo apt-get install ruby irb ri rdoc ruby1.8-dev libzlib-ruby libyaml-ruby libreadline-ruby libncurses-ruby libcurses-ruby libruby libruby-extras libfcgi-ruby1.8 build-essential libopenssl-ruby libdbm-ruby libdbi-ruby libdbd-sqlite3-ruby libsqlite3-dev libsqlite3-ruby libxml-ruby libxml2-dev

  • Installing RubyGem.

Download RubyGem, extract it to a directory and execute:

sudo ruby setup.rb

  • Installing Ruby/GTK.

sudo apt-get install libgtk2.0-dev ruby-gnome2

  • Installing RuGUI and RSpec.

sudo gem install rugui rspec

  • Creating your first RuGUI project.

rugui my-first-project

  • Starting the project

cd my-first-project
rake run

Filed under: gtk

chak says...

http://www.haskell.org/haskellwiki/Gtk2Hs#Using_the_GTK.2B_OS_X_Framework

Filed under: gtk

Alec says...

This is a followup to my previous post.

A fairly common pattern in GTK code seems to be updating a widget whenever a value changes in your controller. That is, something like this:

class Counter(gobject.Gobject):
  __gsignals__ = {
    'counter-changed': (gobject.SIGNAL_RUN_FIRST,
                        gobject.TYPE_NONE, (int,)),
    }

  def __init__(self):
    self.counter = 0

  def inc(self):
    self.counter += 1
    self.emit('counter-changed', self.counter)

  def dec(self):
    self.counter -= 1
    self.emit('counter-changed', self.counter)


Needless to say, this can get a bit tedious. With a bit of stack frame hackery we can reduce that boilerplate to the following:

class Counter(gobject.GObject):
  counter = SignalProperty('counter-changed', 0)

  def inc(self):
    self.counter += 1

  def dec(self):
    self.counter -= 1


Here's the code:

class SignalProperty(object):
  def __init__(self, name, default=None):
    self.name =  name
    self.default = default
    frame = sys._getframe(1)
    locals_ = frame.f_locals
    signals = locals_.setdefault('__gsignals__', {})
    signals[name] = (gobject.SIGNAL_RUN_FIRST,
                     gobject.TYPE_NONE, (object,))

  def __get__(self, instance, owner):
    if instance is None:
      return self
    return getattr(instance, '_signal_' + self.name, self.default)

  def __set__(self, instance, value):
    setattr(instance, '_signal_' + self.name, value)
    instance.emit(self.name, value)



Filed under: gtk

Alec says...

Last week I set out to learn PyGTK by doing. Quickly. As can be imagined, the resulting code was less than stellar, but I did learn a lot.

By far the most glaring design error I made was in not completely decoupling my UI objects from "business" logic, ala MVC. This failure was the result of not totally comprehending the role signals should play in GTK applications. I made the first step correctly, with distinct objects for the UI panel and logic, but sadly that was the last smart choice I made. My next was deciding how to update the UI when the state of the system changed. "Hmm", I thought. "If I just pass the appropriate UI control through to the logic layer, I can update the view as necessary! Brilliant!". BZzzzzzzzzzzzt! Wrong.

The right approach in GTK is to use signals to notify the UI of changes to your objects. To do this, inherit from gobject.Gobject and add a __gsignals__ attribute. Here's a mocked up example of a simulation that emits a "simulation-step" signal every time the simulation is updated. To update a hypothetical counter widget we simply connect the signal to a callback that updates the widget.

class Controller(gobject.GObject):
  __gsignals__ = {
    'simulation-step': (gobject.SIGNAL_RUN_FIRST,
                        gobject.TYPE_NONE, (int,)),
  }

  def step_simulation(self, step):
    self.emit('simulation-step', step)

class View(object):
  def __init__(self, builder, controller):
    # "builder" is a Glade gtk.Builder object.
    builder.connect_signals(self)
    self.step_counter = builder.get_object('step_counter')
    controller.connect('simulation-step', self.on_simulation_step)

  def on_simulation_step(self, simulation, step):
    self.step_counter.set_value(step)

controller = Controller()
view = View(controller)


The fundamental mistake I made was assuming that GTK signals were purely for notifying my application of UI changes. In reality, signals are equally important in notifying the UI of application state changes.

Filed under: gtk

Alec says...

The "easiest" way of integrating threads with PyGTK applications seems to be by using gobject.

Initialisation before starting the GTK main loop:

import gobject
gobject.threads_init()

Schedule any rendering functions from your thread with:

gobject.idle_add(window.queue_draw)

Also useful is the timeout_add function, which schedules periodic callbacks:

gobject.timeout_add(250, window.queue_draw)

Filed under: gtk