pygtk

GECO's picture

Hace ya algún tiempo que hice la interfaz gráfica de GECO y esto lo hice usando glade para generar un fichero xml que posteriormente se carga desde python y se trabaja con los controles. Así se consigue separar la capa de presentación de la lógica del programa y es muy simple cambiar casi cualquier aspecto gráfico sin tener que tocar código.

Para hacer aplicaciones de escritorio con gtk lo más simple es utilizar glade-3, en casi todas las distribuciones hay varios paquetes, glade o glade-2 y glade-3. En las versiones anteriores el editor glade presentaba varias ventanas dispersas, al estilo gimp, pero glade-3 presenta una interfaz unificada y mucho más intuitiva.

Es muy sencillo crear una interfaz con este programa, sólo tienes que ir pinchando en los controles que quieras añadir y se van dibujando sobre la marcha, luego cambias sus propiedades y le das el aspecto visual que prefieras.

La mayoría de los manuales de pygtk y glade indican que hay que hacer lo siguiente para cargar una interfaz creada con glade desde código python:

  1. import gtk.glade
  2.  
  3. class Ventana:
  4. def __init__(self):
  5. self.gladefile = "window.glade"
  6. self.glade = gtk.glade.XML(self.gladefile)
  7.  
  8. #accediendo a los controles
  9. self.button = self.glade.get_widget('button1')
  10. self.button.connect('clicked', action)

¿Qué simple verdad? pues en principio no funciona, cuando lo intentas hacer no funciona, a no ser que en el glade le des a guardar como libglade. Esto es porque desde hace algún tiempo, y yo no me había enterado, se utiliza otro formato que es gtkbuilder. Para utilizar interfaces generadas con glade y guardadas como gtkbuilder (que es como debería ser) hay que hacerlo de la siguiente manera:

  1. import gtk
  2.  
  3. class Ventana:
  4. def __init__(self):
  5. self.gladefile = "window.glade"
  6. self.glade = gtk.Builder()
  7. self.glade.add_from_file(self.gladefile)
  8.  
  9. #accediendo a los controles
  10. self.button = self.glade.get_object('button1')
  11. self.button.connect('clicked', action)

Como podrás observar no ha cambiado mucho la cosa, solo cambiar get_widget por get_object y poco más.

Una vez cargado un objeto ya se puede trabajar con él, modificándolo, obteniendo información de él, etc. Para conocer todos los métodos y señales disponibles lo mejor es mirar la documentación.

Más facilidades, connect_signals, antiguo autoconnect

Desde glade, además de poner los controles en su sitio y definir los nombres se pueden definir funciones asociadas a los diferentes eventos que el objeto en cuestión pueda recibir. Así podemos evitarnos el tener que enlazar todos los botones con sus correspondientes funciones con el método connect, como se puede ver en los ejemplos anteriores y se pueden enlazar todas las funciones con una serie de funciones o métodos definidos.

Supongamos que tenemos una interfaz con un par de botones y hemos enlazado la señal clicked de cada botón con dos funciones llamadas boton1 y boton2 respectivamente.

glade-sample

Para que estos botones hagan algo, tendríamos un código así:

  1. import gtk
  2.  
  3. class Ventana:
  4. def __init__(self):
  5. self.builder = gtk.Builder()
  6. self.builder.add_from_file('test.glade')
  7. self.window = self.builder.get_object('window1')
  8. self.window.show_all()
  9.  
  10. # Magia :P
  11. self.builder.connect_signals(self)
  12.  
  13. def boton1(self, widget):
  14. print "boton1"
  15.  
  16. def boton2(self, widget):
  17. print "boton2"
  18.  
  19. if __name__ == '__main__':
  20. v = Ventana()
  21. gtk.main()

Si al método connect_signals se le pasa una instancia, buscará el nombre de las funciones en sus métodos, sin embargo también puede recibir un diccionario, y en tal caso, buscará las funciones a enlazar en ese diccionario.

También es posible pasarle argumentos a las funciones, pasándole otro argumento al método connect_signals:

  1. ...
  2. self.builder.connect_signals(self, 'mas info')
  3. ...
  4. def boton1(self, widget, data):
  5. ...
  6. def boton2(self, widget, data):
  7. ...

Y con esto y un bizcocho, hacer interfaces gráficas con pygtk y glade es mucho más simple de lo que nunca pudieras imáginar :P