PyGTK/Hello World with Glade

From OLPC
< PyGTK
Revision as of 19:40, 28 January 2009 by Bugger me backwards (talk | contribs) (PyGTK/Hello World with Glade moved to Q16: Bugger me backwards)
Jump to: navigation, search
This is an on-going translation
THIS IS A TRANSLATION INTO ENGLISH OF A FOREIGN WIKI-PAGE IN SPANISH 
Tuquito | SITE | WIKI | ORIGINAL | VERSION | DIFF

Here we'll see how to do a the classical Hello World! in Sugar using Python, GTK and Glade.

Let's start out with Glade: make a simple window, a textbox and a button, which when pressed will display “¡Hola Mundo!” in the textbox.

First we must create the window selecting the window icon from Glade's palette. We then create the vertical box by clicking on the corresponding widget palette. The box will have two rows, as seen in the pictures below.

Vamos a hacer el clásico Hola Mundo, en Python + GTK usando Glade, para que funcione en Sugar.

Empecemos con Glade: vamos a hacer una ventana simple, con una caja de texto y un botón. Al presionar el botón tiene que aparecer el “¡Hola Mundo!” en la caja de texto:

Primero creamos la ventana seleccionando el ícono de “ventana” desde la ventana “Paleta” de Glade. Luego creamos una caja vertical haciendo click en el icono correspondiente de la Paleta de widgets. La caja tendrá dos filas, como se ve en las figuras.

In the top row we'll place an entry field by first clicking on the icon in the palette and then on the top row itself. We do the same with the bottom row, but using a button. We can change the entry field and button's name as well as the text displayed on the button by opening Glade's properties window. We've labeled the button as “boton”, “texto” for the entry field and “cajavertical” for the enclosing vertical box.

En la fila de arriba ponemos una entrada de texto haciendo click en el icono correspondiente de la paleta y luego en la primera fila de la caja vertical. Hacemos lo mismo para crear un botón en la fila de abajo. Podemos cambiar el nombre del botón y la entrada de texto así como el texto del botón desde la ventana de propiedades de Glade. Yo le puse “boton” al botón, “texto” a la entrada de texto y “cajavertical” a la caja vertical que los contiene.

Tuquito-HelloWorld-BotonTexto.jpg

Now we'll write the function which will be executed when we click on the button. We must first select the button and then the signals tab in the properties window. By clicking on the button with '...' we can select which signal to handle. In the menu we select the 'clicked' signal and then hit Accept. We push now the other Accept to add the manager (the actual function to invoke) with the default name (“on_boton_clicked” which will vary depending on the name previously given ).

Ahora vamos a designar la funcion que se va a ejecutar cuando hagamos click en el botón. Para esto (habiendo seleccionado el botón), en la ventana propiedades, vamos a la pestaña “señales”. Presionamos el botón con puntos suspensivos (...) para elegir la señal a manejar. En el menú elegimos la señal “clicked” y apretamos “Aceptar”. Luego presionamos “Agregar” para agregar el manejador (la función que se ejecutará) de esa señal con el nombre por defecto (“on_boton_clicked” dependiendo del nombre que le pongan al botón).

We must now save the Glade file. It's important to highlight the required directory structure be as follows:

 HolaActivity/
              activity/
                       holamundo/
                                 holamundo.glade


Guardamos el archivo de Glade. Es importante tener una estructura de directorios como la siguiente:

HolaActivity/ activity/ holamundo/ holamundo.glade

Now we can code! As you will see the code is extremely simple (after all this is a Hello World!). We must first make the core—the part actually doing something. Let's take a look at the code:

  # HolaActivity/holamundo/HolaMundo.py
  import pygtk
  pygtk.require('2.0')
  
  import os
  import gtk
  import gtk.glade
  
  from sugar.activity import activity
  
  class HolaMundo():
      def __init__(self):
          holadir = os.path.join(activity.get_bundle_path(), 'holamundo')
          archiglade = gtk.glade.XML(os.path.join(holadir, 'holamundo.glade'), 'cajavertical')
          self.caja = archiglade.get_widget('cajavertical')
          self.cajatexto = archiglade.get_widget('texto')
          archiglade.signal_autoconnect(self)
          
      def on_boton_clicked(self, widget):
          self.cajatexto.set_text('Hola Mundo!')

Bueno, ¡a codificar!. Como verán el código es muy fácil y simple (después de todo es un hola mundo). Primero armamos la parte central, la que hace realmente el trabajo. Miremos el código:

# HolaActivity/holamundo/HolaMundo.py import pygtk pygtk.require('2.0')

import os import gtk import gtk.glade

from sugar.activity import activity

class HolaMundo(): def __init__(self): holadir = os.path.join(activity.get_bundle_path(), 'holamundo') archiglade = gtk.glade.XML(os.path.join(holadir, 'holamundo.glade'), 'cajavertical') self.caja = archiglade.get_widget('cajavertical') self.cajatexto = archiglade.get_widget('texto') archiglade.signal_autoconnect(self)

def on_boton_clicked(self, widget): self.cajatexto.set_text('Hola Mundo!')

If you know some PyGTK+Glade, you'll see nothing new in the code, except maybe for the following two points:

  1. We use the activity module from Sugar in order to obtain the activity's current directory, which allows us to load the glade file.
  2. When we load the glade file, we provide an extra parameter 'cajavertical' in order to avoid loading the whole widget tree, and only from the vertical box that holds the button and entry field. We will not be loading from the window level as Sugar provides us with one as we'll see next.

Si saben PyGTK+Glade, no verán nada novedoso en el código, excepto por los dos siguientes puntos:

Usamos el módulo env de Sugar para obtener el directorio de nuestra aplicación, esto lo hacemos para poder cargar el archivo de glade.

Cuando cargamos el archivo de glade, usamos un parámetro extra ,'cajavertical', el cual indica que no cargue desde el principio del árbol de widgets sino recién a partir de la caja vertical que contiene al botón y a la entrada de texto. No cargamos a partir de la ventana porque Sugar nos provee de una, como veremos a continuación.

We must now write the code that connects our activity with Sugar:

  # HolaActivity/HolaActivity.py
  from sugar.activity import activity
  
  from holamundo.HolaMundo import HolaMundo
  
  class HolaActivity(activity.Activity):
      def __init__(self, handle):
          activity.Activity.__init__(self, handle)
          self.set_title('Hola Mundo')
          hola = HolaMundo()
          self.add(hola.caja)

Ahora escribimos el código que conecta nuestra aplicación con Sugar:

# HolaActivity/HolaActivity.py from sugar.activity import activity

from holamundo.HolaMundo import HolaMundo

class HolaActivity(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) self.set_title('Hola Mundo') hola = HolaMundo() self.add(hola.caja)

Our new class inherits from Sugar's Activity class, which itself inherits from gtk.Window, in other words it provides us with all the behavior of a GTK+ window, and that's the reason why we only load the widget tree starting from the vertical box, instead of the window itself. We then must only add our own widgets by simply using the add method as seen in the code.

Nuestra clase hereda de la clase Activity de Sugar, que hereda de gtk.Window, o sea, nos provee ya de una ventana GTK+, por eso es que en nuestra aplicación cargamos el árbol de widgets a partir de la caja vertical y no desde la ventana misma. Entonces a esta ventana que nos provee Sugar le ponemos encima nuestros widgets, simplemente usando el método add como se ve en el código.

That's it! No more programming. What follow is simply the configuration and packaging in order to install the activity in Sugar, using the package known as bundle-builder.

First we must create in the activity subdirectory a file named activity.info that holds the information required by Sugar about our activity:

 [Activity]
 name = HolaActivity
 id = org.tuquito.HolaActivity
 service_name = org.tuquito.ejemplos.HolaActivity
 class = HolaActivity.HolaActivity
 icon = tuquito
 show_launcher = yes
 activity_version = 1
 host_version = 1

Hasta acá la parte de programación. Lo que sigue es simplemente la configuración para instalar la actividad en Sugar, vamos a usar un paquete llamado bundle-builder.

Primero creamos en el subdirectorio activity el archivo activity.info que contiene la información que Sugar tiene que conocer acerca de nuestra actividad:

[Activity] name = HolaActivity id = org.tuquito.HolaActivity service_name = org.tuquito.ejemplos.HolaActivity class = HolaActivity.HolaActivity icon = tuquito show_launcher = yes activity_version = 1 host_version = 1

The parameter name indicates the name of the activity, service_name will be the name used to register with DBus; class indicates how will Sugar invoke our activity, thus it must be the name of our main activity file followed by a period and the name of the class that launches the activity defined in it (similar to what you would an import in Python); icon will be the file name of the icon used to represent the activity and must be an SVG file included in the activity subdirectory specified here; finally, show_launcher indicates if the activity will appear on the Frame to launch it—in other words, if the icon will show or not on the Launch border of the Frame.

El parámetro name indica el nombre de nuestra actividad; service_name es el nombre con el cual se va a registrar en Dbus; class indica cómo llamará Sugar a nuestra actividad, se debe poner el nombre de nuestro archivo de actividad principal, un punto y el nombre de la clase principal de nuestra actividad definida en ese archivo (como si la importaramos desde python); icon indica el icono que representará a nuestra actividad, éste tiene que ser un archivo SVG y debe estar en el subdirectorio activity con el nombre indicado en este parámetro; finalmente show_launcher indica si se podrá lanzar la actividad desde el marco de Sugar (o sea, si aparece el icono o no).

We must now create a file named setup.py with just the following:

 # HolaActivity/setup.py
 from sugar.activity import bundlebuilder
 bundlebuilder.start()

Ahora creamos un archivo que se llame setup.py, unicamente con el siguiente contenido:

# HolaActivity/setup.py from sugar.activity import bundlebuilder bundlebuilder.start()

Next we must create a file named MANIFEST in which we indicate which are the files that are part of the activity bundle:

 HolaActivity.py
 holamundo/HolaMundo.py
 holamundo/holamundo.glade

A continuación creamos un archivo que se llama MANIFEST en el cual indicamos cuáles son los archivos que conforman el paquete o “atado” (bundle) de la actividad:

HolaActivity.py holamundo/HolaMundo.py holamundo/holamundo.glade

If you note, you will see that we don't include the activity's directory, this is not needed as the bundle-builder does it for us.

Done! After this step we should have an activity ready to be installed in Sugar. So let's review some things. We must have the following directory tree structure for our activity:

  HolaActivity/
               HolaActivity.py
               setup.py
               holamundo/
                         holamundo.glade
                         HolaMundo.py
               activity/
                        activity.info
                        tuquito.svg

Si se fijan, notarán que no incluimos el directorio activity, no es necesario porque el bundlebuilder lo hace por nosotros.

Bueno, con esto ya tendríamos una actividad preparada para instalarse en Sugar. Repasemos un poco. Tenemos el siguiente árbol de nuestra actividad:

HolaActivity/ HolaActivity.py setup.py holamundo/ holamundo.glade HolaMundo.py activity/ activity.info tuquito.svg

The file HolaActivity/HolaActivity.py defines the class that interacts with Sugar and loads the class in the file HolaActivity/holamundo/HolaMundo.py that itself loads the glade file and handles the events (there's no need to keep them in separate files, it's done like that because in more complex activities is more convenient and as a side effect it allows the application to run without Sugar). In the activity directory we declare the data of our activity. The setup.py file is the installation script for the activity which reads the file list in the MANIFEST to determine the files to install.

Let's now then install the activity HolaMundo:

$ /path/to/sugar-jhbuild/sugar-jhbuild shell
$ python setup.py dev
$ python setup.py install /path/to/sugar-jhbuild/build

El archivo HolaActivity/HolaActivity.py define la clase que interactúa con Sugar y carga la clase del archivo HolaActivity/holamundo/HolaMundo.py que carga el archivo de glade y maneja los eventos (no es necesario tenerlo en directorios o incluso archivos separados, lo hago porque para actividades grandes es mas conveniente, además de poder tener aplicaciones que funcionen sin Sugar). En el directorio activity declaramos los datos de nuestra actividad. El archivo setup.py es el script de instalación de la actividad y lee de MANIFEST la lista de archivos a instalar.

Instalemos, entonces, la actividad HolaMundo:

$ /ruta/a/sugar-jhbuild/sugar-jhbuild shell $ python setup.py dev $ python setup.py install /ruta/a/sugar-jhbuild/build

By doing this we now have the Activity bundle installed within Sugar. The first command adds, amongst other things, to the Python path the Sugar libraries, needed execute the setup.py installation script. We then prepare the Activity bundle by doing python setup.py dev resulting in a symbolic link to an Activities' subdirectory pointing to the activity in our own personal subdirectory. Finally, the las command effectively installs the “Hola Mundo” in Sugar's directory tree.

Con esto ya queda instalado el “atado” dentro de Sugar. El primer comando agrega, entre otras cosas, a la ruta de Python la ruta hacia las librerías de Sugar, necesarias para ejecutar el script de instalación setup.py. Luego preparamos el paquete para desarrollo con el comando python setup.py dev con lo cual obtenemos un enlace simbólico al directorio de la actividad en un subdirectorio Activities de nuestro directorio personal. Finalmente, el último comando instala efectivamente el “Hola Mundo” dentro del árbol de Sugar.

If we now execute sugar-emulator (or /path/to/sugar-jhbuild/sugar-jhbuild run—effectively the same thing) we should see our activity icon appear with the Launch border of the Frame... click on it to launch it...

Si ejecutamos sugar-emulator (o /ruta/a/sugar-jhbuild/sugar-jhbuild run, que es lo mismo) debería aparecer el icono de nuestra actividad en la parte inferior del marco y ejecutarse al hacer click sobre ella.

That's all for now. The intention is to follow-up with some tutorials on DBus, Sugar's presence API and more... you can check for updates in Tuquito (and then follow to the external sites).

Esto es todo por ahora, proximamente habrá mas tutoriales de DBus, la presence API de Sugar y mucho mas.