"Hola Mundo" con Python y GtkBuilder

Hola, este es el primer tutorial que publico, espero con el tiempo mejorar mi calidad de redacción. Ahí va:

Vamos a ver como crear un sencillo programa que muestre un botón y al hacer click en él despliegue el mensaje "Hola mundo". Con este ejemplo se podrán aprender los pasos que en general se van a aplicar a cualquier otro programa hecho en Python y GtkBuilder. Hacer click en las imágenes para verlas en tamaño completo.

Herramientas necesarias:
Para construir la interfaz gráfica, vamos a usar Glade, un constructor de interfaces Gtk+.

Luego, necesitamos Python y los bindings de Gtk+ para Python.

Para este tutorial vamos a usar un IDE llamado Geany, que destaca por lo liviano y rápido que resulta.

Para instalar todo esto de una vez, en Debian/Ubuntu, simplemente ejecutamos el comando "sudo apt-get install python python-gtk2 glade geany" (sin comillas) en una consola. En Arch: "sudo pacman -Sy python pygtk glade geany".

(Nota: si usás Debian, asegurate de tener Squeeze para adelante para que te sirva el tutorial. Debian Lenny tiene versiones muy antiguas de glade, python y python-gtk y algunas cosas podrían ser diferentes).

Diseño de la interfaz:
Luego de instalar todo lo necesario, vamos a diseñar la interfaz de usuario de nuestra aplicación. Para eso, abrimos Glade.

En esta ventana dejamos las opciones como en la imagen y damos click a Cerrar:

Ahora se nos presenta la pantalla principal de Glade:

Creamos la ventana principal para nuestro programa, para eso hacemos click en la herramienta Ventana, el resultado es el siguiente:

Ahora agregamos una botonera (el lugar en donde van los botones) de un solo elemento y dentro de el espacio que se crea en nuestra ventana principal agregamos un botón:

Seleccionamos el botón y en la caja de propiedades, bajo la pestaña General, le ponemos por nombre "boton" y luego buscamos la propiedad Etiqueta y le cambiamos lo que tenga por "Click aquí":
Como se puede ver, lo que vaya en la propiedad Etiqueta es el texto que va a tener el botón. El nombre que lo pusimos ("boton") nos va a servir para poder referirnos al boton y programarlo en el momento de escribir el código. Podemos ponerle cualquier nombre, lo que no es posible es dar a dos elementos distintos de la interfaz el mismo nombre.

Vamos a la pestaña Señales de las propiedades de nuestro botón, y en la señal "clicked" seleccionamos el manipulador "on_boton_clicked" (enseguida explico esto):

A continuación vamos a crear la ventana a mostrarse al hacer click en el botón. Para eso, creamos una nueva ventana de la misma manera en la que creamos la ventana principal y dentro de ella insertamos una etiqueta con la herramienta Etiqueta:
Cambiamos el texto de la propiedad Etiqueta de nuestra etiqueta por "Hola Mundo", bajo la pestaña General de sus propiedades:
Solo para hacer más fácilmente entendible todo, le cambiamos los nombres a las ventanas. Le ponemos "ventanaprincipal" a lo que era window1 y "ventanamensaje" a lo que era window2:
Por último, le damos el manipulador "on_ventanaprincipal_destroy" a la señal destroy de nuestra ventana principal:
Los manipuladores son la forma de llamar a las señales de cada elemento de nuestro programa a la hora de escribir el código. Por ejemplo, cuando programemos el manipulador "on_ventanaprincipal_destroy", estaremos dando las instrucciones a ser ejecutadas al momento de cerrar (destruir) la ventana principal de nuestro programa; cuando se cierre la ventana principal esta da la señal "destroy" y se ejecuta lo que hayamos programado en su manipulador. Lo mismo pasa con el boton, cuando se haga click en el este da la señal "clicked" y se ejecuta el código que escribamos en su manipulador. (Nota: esto es lo que aprendí y me funciona, y creo que se acerca mucho a lo que realmente sucede, pero podría no ser realmente la explicación más correcta sobre las señales y los manipuladores).

Antes de pasar al código en sí, guardamos nuestra interfaz como "mundo.xml" en el formato GtkBuilder. Para eso nos vamos a Archivo-Guardar Como y le damos "mundo.xml" como nombre a nuestro archivo, seleccionamos GtkBuilder en formato de archivo y damos click en Guardar.

Código del programa:
Ahora pasamos a la parte más importante de cualquier programa: su código.

Abrimos Geany:
Ahora comenzamos a escribir el código:

Primero importamos los módulos que vamos a utilizar:

import gtk
import pygtk

Ahora creamos una clase que llamaremos "mundo", que va a contener los elementos del programa y las instrucciones que le vamos a dar a cada uno de los manipuladores de las señales, y comenzamos a importar los elementos de nuestra interfaz gráfica:

class mundo:
   def __init__(self):
      b= gtk.Builder()
      b.add_from_file("mundo.xml")
      self.ventanaprincipal = b.get_object("ventanaprincipal")
      self.boton = b.get_object("boton")
      self.ventanamensaje = b.get_object("ventanamensaje")
      b.connect_signals(self)
      self.ventanaprincipal.show()

Explicando línea por línea: primero se crea la clase, luego se define el "constructor". Dentro del mismo, agregamos el archivo "mundo.xml" que habíamos creado, y empezamos a importar de ese archivo cada uno de los elementos de nuestra interfaz. Después eso se conectan las señales y se muestra la ventana principal.

Vamos a definir ahora qué se hace al dar click al botón:

   def on_boton_clicked(self, widget, data=None):
      self.ventanamensaje.show()

Simplemente se muestra la ventana "ventanamensaje", que contiene el texto "Hola Mundo" al hacer click en el botón.

Ahora definimos qué hacer cuando se cierre la ventana principal:

   def on_ventanaprincipal_destroy(self, widget, data=None):
      gtk.main_quit()

Esto indica que termina el programa.

Por último, iniciamos la clase y el método gtk.main(), que se encarga de recibir las señales de los elementos de nuestra interfaz. Con estas dos líneas se da inicio al programa:

mundo()
gtk.main()


Guardamos el archivo como "mundo.py" en la misma carpeta en la que está el archivo "mundo.xml" creado anteriormente y lo ejecutamos directamente desde Geany presionando F5:

Al ejecutar el programa aparece la ventana principal con un botón. Al presionar el botón aparece otra ventana con el texto "Hola Mundo". Todo tiene una apariencia bastante mala, y vamos a ver en el siguiente tutorial como mejorar ese aspecto.

27 comentarios: (+add yours?)

chuche dijo...

Gracias por el tuto, ya lo hice y me ha salido muy bien, en lo único que me tarde fue en el código ya que cambie los nombres de las ventanas y el del botón, de ahí en adelante todo bien ^_^

Anónimo dijo...

buen tutorial!

ito123456789 dijo...

Muhísimas gracias!

Este jueves ya termino mis examenes y saco un nuevo tutorial.

Anónimo dijo...

Excelente tuto, espero puedas continuar de esta manera. Es difícil encontrar información tan sencilla y oportuna como la que brindas o al menos me ha costado mucho trabajo hacerlo.

Felicidades y sigue así...

alex dijo...

magnifico tutorial, felicidades y queria hacer una pregunta a ito123456789 o a cualquiera que pueda responderme, se puede hacer todo un programa completo con botones, menues y todo lo mas simple posible en un solo archivo como ejemplo podemos poner que todo esta contenido en el archivo llamado "ejemplo.py" con los permisos correspondientes.

ito123456789 dijo...

Gracias! Claro que podés hacer eso, pero para eso tendrías que usar la biblioteca GTK directamente, sin usar Glade, e ir creando cada elemento directamente en tu código, por ejemplo para hacer una ventana harías ventana = gtk.window(), luego le agregas los elementos con ventana.add(elemento) y así.

alex dijo...

pero mi pregunta entonces seria,puedo usar esta interfaz grafica sin usar glade

ito123456789 dijo...

No te entendí ahora... si lo hacés como te dije no necesitas nada más que tu editor de texto, todo lo hacés directamente desde el código fuente, un solo archivo. No usás Glade.

Mirá un tutorial, voy a escribir uno propio después de los exámenes:
http://www.linuxlots.com/~barreiro/spanish/gtk/tutorial/gtk_tut.es.html

alex dijo...

mi pregunta es que si se puede usar el geany, el python, el gtk para hacerlo en un entorno visual. o sea sin usar glade, es que quiero hacer un navegador sencillito y talvez usted pueda ayudarme.

alex dijo...
Este comentario ha sido eliminado por el autor.
GLMauricio dijo...

ito: Ayuuuudaaaa por favor...
Por que me da este error?
Traceback (most recent call last):
File "", line 1, in
mundo()
File "C:\Python26\programas\mundo.py", line 6, in __init__
b.add_from_file("mundo.xml")
GError: Etiqueta no soportada: «requires»

mundo.xml está en la misma carpeta que mundo.py...

ito123456789 dijo...

No estarás usando Debian Lenny o si? En ese caso no puedo ayudarte.

GLMauricio dijo...

no..
Windows.
Python 2.6.5
Glade 3.6.1
gtk 2.12.9
pygtk 2.12
Generé mundo.xml y lo grabe en la misma carpeta que mundo.py
Mundo.py

y este es el código

import gtk
import pygtk
class mundo:
def __init__(self):
b=gtk.Builder()
b.add_from_file("mundo.xml")
self.ventanaprincipal = b.get_object("ventanaprincipal")
self.boton = b.get_object("boton")
self.ventanamensaje =b.get_object("ventanamensaje")
b.connect_signals(self)
sel.ventanaprincipal.show()
def on_boton_clicked(self, widget, data=None):
self.ventanamensaje.show()
def on_ventanaprincipal_destroy(self, widget, data=None):
gtk.main_quit()

ito123456789 dijo...

Creo que hasta en Debian Lenny estarías mejor... Fijate si instalaste todo bien, mi experiencia con Windows es nula, no se usarlo y no puedo ayudarte.

Tu código está perfecto, así que ese no es el problema. Si tenés problemas con el lenguaje no dudes en preguntarme.

Linexteria dijo...

Excelente tutorial, pero al ejecutar el Geany como tu dices, no me aparece la interfaz ejecutada, solo una raya negra..

el código que tengo es:
import gtk
import pygtk

class mundo:
def _init_(self):
b= gtk.builder()
b.add_from_file("mundo.xml")
self.ventanaprincipal = b.get_object("ventanaprincipal")
self.boton = b.get_object("boton")
self.ventanamensaje = b.get_object("ventanamensaje")
b.connect_signals(self)

self.ventanaprincipal.show()

def on_boton_clicked(self, widget, data=None):
self.ventanamensaje.show()

def on_ventanaprincipal_destroy(self, widget, data=None):
gtk.main_quit()

mundo()
gtk.main()

alguna soluciòn.

ito123456789 dijo...

Linexteria tenés que poner __init__(self). Con dos guiones bajos a cada lado.

Y además es gtk.Builder, con la B mayúscula.

Espero que se solucione tu problema.

Linexteria dijo...

Ok Man, lo acabo de comprobar y funciona bien..

saludos y gracias..

Johomali dijo...

Da error en varias lineas... Agradezco ayuda....
#***********************************************
# Server TCP/IP
#***********************************************
#!/usr/bin/env python
import gtk
import pygtk
class mundo:
def __init__(self): # funcion
b = gtk.Builder() # Genera las ventanas
b.add_from_file("mundo.xml")
self.ventanaprincipal = b.get_object("ventana") # Variable
self.boton = b.get_object("boton") # Variable
self.ventanamensaje = b.get_object("Ventana1") # Variable
b.connect_signals(self)
self.ventanaprincipal.show()
def on_boton_clicked(self, widget, data=None):
self.ventanamensaje.show()
def on_ventanaprincipal_destroy(self, widget, data=None):
gtk.main_quit()
mundo()
gtk.main()

mundo.py:14: RuntimeWarning: missing handler 'on_Ventana.png_activate_default'
b.connect_signals(self)
Traceback (most recent call last):
File "mundo.py", line 20, in
mundo()
File "mundo.py", line 15, in __init__
self.ventanaprincipal.show()
AttributeError: 'NoneType' object has no attribute 'show'
administrador@ubuntu:~/programasPython$ gedit

Johomali dijo...
Este comentario ha sido eliminado por el autor.
Anónimo dijo...

funciono +10

sigue con esto que tenes talento...
y gracias por el tuto

Anónimo dijo...

Hola que tal, encuentro este tuto algo tarde, pero seguí los pasos en Glade y en Geany sin embargo al presionar F5 obtengo una ventana emergente del programa ".sh" con determinado error, quisiera que me indique al respecto que puedo hacer, Uso Debian Squeeze (Stable) v 6.0.3

File "mundo.py", line 4
def__init__(self):

SyntaxError: invalid syntax

------------------
(program exited with code:1)
Press return to continue


Saludos,

Muchas gracias de antemano, me disculpo por el desorden, porque ninguna de las etiquetas HTML que escribí fue aceptada.

ito123456789 dijo...

Hola Anónimo, es un simple error de sintaxis: Pusiste def__init__(self) todo junto, y tiene que haber un espacio entre def y __init__, así:

def __init__(self):

Anónimo dijo...

Hola amigo, le agradezco su atención.

Me disculpo ya que si lo habia escrito con error de syntaxis ya que lo estuve pasando a mano, pero en el programa lo tengo correctamente escrito, sin embargo aún así contiuan los errores.

Acá la vista de como lo copié a Glade, por la red leí que indentación se refiere a espacio o posición que ocupa una sintaxis en su linea, es decir, si queda o no anidada correctamente la sintaxis dentro de un bloque etc... pero por mas cambios que le agrego no consigo que ruede satisfactoriamente...
*****************************************************************

#! /usr/bin/env python
# -*- coding: UTF-8 -*-

import gtk
import pygtk

pygtk.require("2.0")

class mundo:
def __init__(self):
b= gtk.Builder()
b.add_from_file("mundo.xml")
self.ventanaprincipal = b.get_object("ventanaprincipal")
self.boton = b.get_object("boton")
self.ventanamensaje = b.get_object("ventanamensaje")
b.connect_signals(self)
self.ventanaprincipal.show()
def on_boton_clicked(self, widget, data=None):
self.ventanamensaje.show()
def on_ventanaprincipal_destroy(self, widget, data=None):
gtk.main_quit()
mundo()
gtk.main()

*****************************************************************
El error que muestra al hacer run es:

File "mundo.py", line 18
def on_boton_clicked(self, widget, data=None):
^
TabError: inconsistent use of tabs and spaces in indentation

que me recomienda al respecto?

Saludos,

ito123456789 dijo...

"TabError: inconsistent use of tabs and spaces in indentation"

Hola, ese error se muestra si combinas espacios y tabs en Python 3.

El tutorial lo escribí usando Python 2, y de todas formas es mala costumbre combinar ambas cosas, dependiendo de qué te parece mejor tendrías que decidirte por espacios o tabulaciones.

Espero haber ayudado, gracias por leerme.

HoradelTe dijo...

Mira no se porque pero no me corre: tengo win64 y me sale cmd y dice: "python" no se reconoce como un comando interno o externo.
p.d esta exacto al tuyo

Anónimo dijo...

ya revise todo el codigo pero no se ejecuta el programa, al darle ejecutar sale la venta cmd y no sale nada mas
te agradesco si me una solucion gracias

Anónimo dijo...

Mi nombre es Roy Hernandez... De costa Rica ..tengo un ligero problema
puedo correr el programa muy bien pero cuando cierro la ventana ultima y la vuelvo abrir esta en blanco...quizas me puedan ayudar

Publicar un comentario