Cómo usar: TreeView

10 comentarios

Veamos cómo cargar y mostrar datos en un TreeView.

Para todos los ejemplos vamos a usar una simple ventana con un TreeView y un botón hechos con Glade:

Popular directamente
Para agregar elementos al TreeView se siguen tres pasos: crear una lista con los elementos, crear las columnas necesarias para el TreeView, y por último asignarles la lista y las columnas creadas. Veamos cómo hacerlo:

Creamos la lista y le agregamos los elementos:
   def populartreeview(self):
      lista=gtk.ListStore(str)
      lista.append(["Negro"])
      lista.append(["Verde"])
      lista.append(["Blanco"])


Creamos la columna:
      render=gtk.CellRendererText()
      columna=gtk.TreeViewColumn("Colores",render,text=0)


Asignamos la lista y la columna al TreeView:
      self.vista.set_model(lista)
      self.vista.append_column(columna)
      self.vista.show()


Obs.: si necesitamos que hayan más columnas, sólo debemos modificar la forma en que se crea la lista, por ejemplo, para almacenar una cadena y un número entero en cada elemento, usamos lista = gtk.ListStore(str,int). Además hay que crear las columnas necesarias y asignarlas al TreeView. Ejemplo:

   def populartreeview(self):
      lista=gtk.ListStore(str,int)
      lista.append(["Negro",12])
      lista.append(["Verde",11])
      lista.append(["Blanco",13])

      render=gtk.CellRendererText()
      columna1=gtk.TreeViewColumn("Colores",render,text=0)
      columna2=gtk.TreeViewColumn("Precios",render,text=1)

      self.vista.set_model(lista)
      self.vista.append_column(columna1)
      self.vista.append_column(columna2)
      self.vista.show()




Obtener elementos
Usemos el botón que creamos para obtener el elemento seleccionado de la vista.

Nos aseguramos de darle el manipulador on_boton_clicked a la señal clicked del botón y escribimos el siguiente método para obtener la selección:

   def on_boton_clicked(self, widget, data=None):
      (model,iter)=self.vista.get_selection().get_selected()
      if iter != None:
         print list(model[iter])


Podemos hacer lo que queramos con los datos obtenidos, en el ejemplo simplemente los imprimimos.

Descargar programa ejemplo

Añadir ícono a la bandeja del sistema

6 comentarios

Veamos cómo añadir un ícono para nuestras aplicaciones en la bandeja del sistema, y cómo agregar un menú a este ícono.

Como siempre, en los tutoriales trabajamos con Geany y Glade 3.

Hagamos un sencillo programa que consista sólo de un ícono en la bandeja del sistema, que muestre un mensaje si recibe un click izquierdo, y despliegue un menú si recibe uno derecho.

Crear el ícono
Abrimos Glade y agregamos un "Ícono de Estado" (nombre que le da GTK+ al ícono que va en la bandeja):

Le damos nombre y una imagen, yo le puse "iconobandeja" y usé esta imagen. La imagen la seleccionamos en la propiedad "Pixbuf":

Ahora le damos manipuladores a las señales "activate" y "popup_menu":

Guardamos el archivo y abrimos nuestro IDE (Geany). Para este tutorial guardé el archivo como "interfaz.xml".

Importamos los módulos necesarios, creamos la clase y el constructor, y corremos el programa:

import pygtk
import gtk

class icono:
   def __init__(self):
      builder = gtk.Builder()
      builder.add_from_file("interfaz.xml")
      self.iconobandeja = builder.get_object("iconobandeja")

      builder.connect_signals(self)

icono()
gtk.main()


Click izquierdo en el ícono
El programa anterior no hace en realidad nada más que mostrar el ícono en la bandeja. Programemos ahora el manipulador de la señal "activate", que se ejecuta cuando el ícono recibe un click izquierdo.

Hagamos que se muestre una ventana con un mensaje. Para hacer más interesante esto (y no estar creando la ventana en Glade), hagamos la ventana en Gtk+ puro (es importante conocer al menos lo básico).

Agregamos el siguiente método a nuestra clase:

   def on_iconobandeja_activate(self, widget, data=None):
      ventana = gtk.Window()
      etiqueta = gtk.Label()
      etiqueta.set_label("Ventana hecha con Gtk+ puro!")
      ventana.add(etiqueta)
      ventana.show_all()


Lo que hacemos es, explicando línea por línea: creamos una ventana, creamos una etiqueta, establecemos el texto de la etiqueta, la agregamos a la ventana, y por último la mostramos.

Click derecho en el ícono
Programemos ahora el manipulador de la señal "popup_menu", que se ejecuta con un click derecho del ratón, para mostrar un menú.

Abrimos Glade y creamos el menú ("Menu Emergente"). Le ponemos un nombre, en mi caso simplemente le puse "menu".

Luego, a la derecha, en donde dice Widgets damos click derecho al menu que creamos y seleccionamos la opción "Edit...". Vamos a la pestaña Jerarquía y hacemos click en "Añadir" para agregar un elemento.

Vamos a crear un solo elemento para este programa, que permita salir del mismo. Le ponemos nombre y etiqueta ("salir", por ejemplo) y cerramos la ventana de edición del menú.

Le damos el manipulador "on_salir_activate" a la señal activate del elemento que acabamos de crear para nuestro menú.




Guardamos el archivo y vamos al IDE a escribir el código.

Agregamos el menu al constructor:
      self.menu = builder.get_object("menu")
      self.salir = builder.get_object("salir")


Creamos el método del manipulador de la señal popup_menu, para desplegar el menú cuando se reciba un click derecho:
   def on_iconobandeja_popup_menu(self, widget, button, activate_time):
      self.menu.popup(None, None, None, button, activate_time)


Por último programamos el elemento que agregamos a nuestro menú:
   def on_salir_activate(self, widget, data=None):
      gtk.main_quit()


El resultado debería de ser el siguiente:

Con un click derecho debe de aparecer un menú con un elemento que diga "Salir", y al hacer click en éste el programa debe terminar.

Descargar programa ejemplo

Cómo usar: ComboBox (II)

5 comentarios

Veamos algunos ejemplos más.

Popular ComboBox desde un archivo de texto:
Supongamos que tenemos almacenada una serie de datos en un archivo de texto, por ejemplo:

Zapatos,Camisas,Pantalones,Remeras,Shorts,Gorras

En este archivo tenemos varios elementos separados por comas. Llamémoslo "Archivo.txt".
Para cargar los elementos a partir de este archivo usamos la siguiente función:

   def popularcombo(self):
      listaelementos=gtk.ListStore(str)
      archivo = open("Archivo.txt","r")
      for line in archivo.readlines():
         i = 0
         cadena = ""
         while i<len(line):
            if line[i] == ",":
               listaelementos.append([cadena])
               cadena = ""
               i = i+1
            else:
               cadena = cadena + line[i]
               i = i+1

      self.combo.set_model(listaelementos)
      render=gtk.CellRendererText()
      self.combo.pack_start(render, True)
      self.combo.add_attribute(render, 'text', 0)

Expliquemos cada línea:
Creamos la función y el objeto listaelementos, en el que vamos a almacenar nuestros elementos:
   def popularcombo(self):
      listaelementos=gtk.ListStore(str)

Abrimos el archivo:
      archivo = open("Archivo.txt","r")

Utilizamos el bucle for para que el proceso se repita por cada línea del archivo (en este ejemplo el archivo tiene una sola línea) e inicializamos algunas variables auxiliares:
      for line in archivo.readlines():
         i = 0
         cadena = ""

Con un bucle while vamos examinando cada caracter de la línea del archivo. Si se encuentra una coma, se agrega a la lista el contenido de la cadena y se vacía la cadena. Si se encuentra cualquier otro caracter, se lo añade a la cadena:
         while i<len(line):
            if line[i] == ",":
               listaelementos.append([cadena])
               cadena = ""
               i = i+1
            else:
               cadena = cadena + line[i]
               i = i+1

Por último le asignamos la lista al ComboBox y mostramos los elementos:
      self.combo.set_model(listaelementos)
      render=gtk.CellRendererText()
      self.combo.pack_start(render, True)
      self.combo.add_attribute(render, 'text', 0)

Descargar programa ejemplo

Popular ComboBox desde una base de datos SQLite:
Supongamos que tenemos una tabla con planetas y sus radios. Para mostrarlos en el ComboBox es simplemente modificar la función anterior de modo que quede de la siguiente manera (Obs.: para trabajar con bases de datos SQLite se debe importar el módulo sqlite3):

   def popularcombo(self):
      listaelementos=gtk.ListStore(str,int)
      bd = sqlite3.connect("Archivo.dat")
      cursor = bd.cursor()
      cursor.execute('SELECT * FROM planetas')
         for row in cursor:
            listaelementos.append(row)

      self.combo.set_model(listaelementos)
      render=gtk.CellRendererText()
      self.combo.pack_start(render, True)
      self.combo.add_attribute(render, 'text', 0)

Explicando:
Cargamos la base de datos y creamos el objeto cursor:
      bd = sqlite3.connect("Archivo.dat")
      cursor = bd.cursor()

Seleccionamos todos los elementos de la tabla "planetas" de nuestra base de datos y añadimos a nuestra lista cada par de datos:
      cursor.execute('SELECT * FROM planetas')
        for row in cursor:
            listaelementos.append(row)

Descargar programa ejemplo

Cómo usar: ComboBox (I)

1 comentarios


Vamos a analizar en este tutorial el uso de los ComboBox.
Como siempre, vamos a utilizar Geany como IDE, Glade y Python.

Comencemos:
Abrimos Glade y creamos una ventana, una botonera de un solo elemento, y dentro de esta botonera, un ComboBox (caja combo).

Le damos nombres a los elementos (es bueno acostumbrarse a hacerlo). Para este tutorial le puse “ventanaprincipal” a la ventana y “combo” al ComboBox.
Damos el manipulador “on_ventanaprincipal_destroy” a la señal destroy de la ventana y guardamos el archivo, en mi caso le puse el nombre “combo.xml”.

Popular el ComboBox:
Veamos como hacer que nuestro ComboBox muestre una lista de elementos.

Abrimos Geany, creamos un archivo nuevo. Importamos los módulos necesarios, creamos la clase y el constructor:

import pygtk
import gtk

class combo:
def __init__(self):
builder = gtk.Builder()
builder.add_from_file("combo.xml")
self.ventanaprincipal = builder.get_object("ventanaprincipal")
self.combo = builder.get_object("combo")

builder.connect_signals(self)
self.ventanaprincipal.show()

Ahora escribamos una función (o método) para cargar los elementos y mostrarlos en nuestro ComboBox:

def popularcombo(self):
listaelementos=gtk.ListStore(str)
listaelementos.append(["Manzanas"])
listaelementos.append(["Peras"])
listaelementos.append(["Naranjas"])

self.combo.set_model(listaelementos)
render = gtk.CellRendererText()
self.combo.pack_start(render, True)
self.combo.add_attribute(render, 'text', 0)

Como se puede ver, lo primero que se hace es crear un objeto de la clase gtk.ListStore(), que nos servirá para almacenar los elementos; el argumento str indica que vamos a almacenar cadenas de texto. Luego agregamos los elementos a la lista, y por último asociamos esa lista a nuestro ComboBox usando self.combo.set_model(). Las tres últimas líneas son las que se encargan de mostrar los elementos en el ComboBox.

Programamos el método "on_ventanaprincipal_destroy", creamos un objeto de la clase combo (la que acabamos de crear) y llamamos a su función "popularcombo()":

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

ejemplo = combo()
ejemplo.popularcombo()
gtk.main()

Guardamos el archivo y ejecutamos el programa:

Obtener un elemento del ComboBox:
El programa anterior no sirve de mucho si no podemos recuperar ningún elemento del ComboBox. Hagamos unas modificaciones al programa de forma que al presionar un botón se obtenga el elemento activo en ese momento.

Abrimos Glade, agregamos un elemento más a la botonera del programa anterior y colocamos un boton en el nuevo espacio (al que para este tutorial llamé "boton" y le puse de etiqueta "Click aquí"). Le damos el manipulador "on_boton_clicked" a la señal clicked del botón y guardamos el archivo.

Hagamos las modificaciones necesarias al código de nuestro programa (las nuevas líneas están en cursiva):

import pygtk
import gtk

class combo:
def __init__(self):
builder = gtk.Builder()
builder.add_from_file("combo.xml")
self.ventanaprincipal = builder.get_object("ventanaprincipal")
self.combo = builder.get_object("combo")
self.boton = builder.get_object("boton")

builder.connect_signals(self)
self.ventanaprincipal.show()

def popularcombo(self):
listaelementos=gtk.ListStore(str)
listaelementos.append(["Manzanas"])
listaelementos.append(["Peras"])
listaelementos.append(["Naranjas"])

self.combo.set_model(listaelementos)
render = gtk.CellRendererText()
self.combo.pack_start(render, True)
self.combo.add_attribute(render, 'text', 0)

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

def on_boton_clicked(self, widget, data=None):
model = self.combo.get_model()
activo = self.combo.get_active()
if activo >= 0:
self.boton.set_label(model[activo][0])


ejemplo = combo()
ejemplo.popularcombo()
gtk.main()

Analicemos las nuevas líneas: en el constructor agregamos el botón y más abajo creamos un nuevo método ("on_boton_clicked"). En este método lo que hacemos es obtener el modelo que está asociado a nuestro ComboBox (la lista de los elementos), obtenemos el número del elemento activo en ese momento en el ComboBox, y por último le damos uso al elemento obtenido (en este tutorial lo usamos para cambiar la etiqueta del botón).
Obs.: Si no seleccionamos ningún elemento (por defecto), el número del elemento activo es -1.

Guardamos el archivo y ejecutamos:

Al dar click al botón:



Ver más ejemplos: Popular desde archivos de texto y desde bases de datos SQLite.

Enviar correo electrónico con Python usando smtplib

8 comentarios

En este tutorial vamos a ver cómo enviar mensajes de correo electrónico usando la biblioteca smtplib. Además vamos a programar una interfaz gráfica que permita tomar el texto de una caja de entrada y enviarlo usando el smtplib.

Herramientas
Vamos a usar, en este tutorial:

  • Geany como IDE.
  • Python (por supuesto).
  • Una versión reciente de Glade (al menos 3.6).
  • Posiblemente haga falta una versión actual de pygtk también.
Uso de smtplib
Para comenzar, vamos a escribir un pequeño programa que sea capaz de enviar un mensaje de email usando una cuenta de Gmail.

Lo primero es importar la biblioteca smtplib:

import smtplib


Ahora generamos el mensaje. Primero pedimos el nombre del remitente, luego la dirección de destino y por último el mensaje en sí:

DE = raw_input("Remitente: ")
PARA = [raw_input("Destino: ")]
texto = """
%s""" % raw_input("Mensaje: ")


Analicemos cada línea: al pedir el remitente no hay nada de especial, cuando pedimos la dirección de destino hay que recordar que se debe guardar como una lista, y, por último, al pedir el texto hay que tener en cuenta que se envía desde la segunda línea para adelante.

Creamos un objeto al que llamamos "server" usando la clase smtplib.SMTP() de la biblioteca smtplib, nos autenticamos y enviamos el mensaje:

server = smtplib.SMTP("smtp.gmail.com:587")
server.starttls()
server.login("nombredeusuario", "contraseña")
server.sendmail(DE, PARA, texto)
server.quit()


Gráficamente
Vamos a crear una interfaz gráfica para el programa anterior.

Abrimos Glade y creamos una ventana con una caja horizontal de cuatro elementos. Le damos por nombre "ventanaprincipal" a nuestra ventana y le ponemos una anchura predeterminada de 400 y una altura predeterminada de 300 en sus propiedades (pestaña General):

En la parte superior de nuestra caja colocamos una vista de texto, en la segunda y en la tercera una entrada de texto, y en la cuarta una botonera de un solo elemento. Dentro de esa botonera colocamos un botón:

Le ponemos nombres a nuestros elementos: a nuestra vista de texto le ponemos "mensaje", a nuestras entradas de texto "remitente" y "destino" (además cambiamos su propiedad "Texto", en la pestaña General, por "Remitente" y "Destino", respectivamente), y a nuestro botón "botonenviar (y le ponemos en su propiedad Etiqueta la palabra "Enviar"):

Le damos el manipulador "on_botonenviar_clicked" a la señal Clicked de nuestro botón y el manipulador "on_ventanaprincipal_destroy" a la señal Destroy de nuestra ventana principal.

En la propiedad Modo de Ajuste de nuestra vista de texto (mensaje), seleccionamos "Palabra", de esta forma al encontrarse que una palabra no cabe en la vista, se baja a la siguiente línea automáticamente.

Vamos a la pestaña Empaquetado de nuestras propiedades y cambiamos la propiedad Expandir de las dos entradas de texto (remitente y destino) y de la botonera por "No". De esta forma todo el espacio de la ventana es reservado para nuestro mensaje, y los demás elementos sólo reciben el espacio necesario para ser visibles:

Guardamos el archivo como "Interfaz.xml".

Abrimos Geany (o cualquier otro IDE o editor de texto) y empezamos a escribir el programa. Primero importamos los módulos necesarios:

import smtplib
import pygtk
import gtk


Creamos la clase "enviaremail" y su constructor:

class enviaremail:
def __init__(self):

builder = gtk.Builder()
builder.add_from_file("interfaz.xml")

self.ventanaprincipal = builder.get_object("ventanaprincipal")
self.mensaje = builder.get_object("mensaje").get_buffer()
self.remitente = builder.get_object("remitente")
self.destino = builder.get_object("destino")
self.botonenviar = builder.get_object("botonenviar")

builder.connect_signals(self)

self.ventanaprincipal.show()


Lo acabamos de hacer fue simplemente crear el objeto "builder" y cargar los elementos que creamos desde el archivo "interfaz.xml". Luego autoconectar todas las señales y mostrar la ventana principal.

Ahora programamos el manipulador para la señal Clicked de nuestro botón (cuando se lo presiona):

def on_botonenviar_clicked(self, widget, data=None):
DE = self.remitente.get_text()
PARA = [self.destino.get_text()]

inicio, fin = self.mensaje.get_bounds()

texto = """
%s
""" % self.mensaje.get_text(inicio, fin)

server = smtplib.SMTP("smtp.gmail.com:587")
server.starttls()
server.login("nombredeusuario", "contraseña")
server.sendmail(DE, PARA, texto)
server.quit()


Como se puede ver, el código es el mismo del primer ejemplo, con algunas diferencias: ahora el destino y el remitente son el contenido de las entradas de texto destino y remitente, respectivamente.
Para el texto del mensaje en sí, la cosa es un poco más complicada. La forma de leer el texto de una vista de texto es estableciendo unas marcas en el inicio y el final del mismo, con la funcion get_bounds(). Éstas marcas se guardan en las variables inicio y fin, que luego se pasan a la función get_text() para conseguir el texto de la vista.

Para terminar creamos el manipulador para la señal Destroy de la ventana principal e iniciamos el programa:

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

enviaremail()
gtk.main()


Guardamos el archivo como "enviaremail.py" y lo ejecutamos: