jueves, 19 de mayo de 2011

wxPython: Obtener datos de las hojas de un AUI_Notebook

Hola. En este post vamos a ver el componente de wxPython AUI Notebook, y en especial su instanciación, creación de hojas y forma de recorrerlas para obtener la información que pudiera haber sido introducida por el usuario.

Hay un ejemplo muy completo en la Demo de wxPython. Aquí se verá lo mismo, más simplificado y con el plus del recorrido de las hojas del AUI Notebook.

El código fuente de esta aplicación se puede encontrar en el repositorio de este blog, en:

https://sites.google.com/site/elviajedelnavegante/

Para poder entender bien como funciona un AUI_Notebook es necesario realizar un ejemplo, ya que es la mejor manera posible. De lo que se trata es de crear un módulo (fichero) que contendrá 2 clases. Una de ellas será el diseño de una hoja (que hereda de wx.Panel), y la segunda clase será un frame que heredará de wx.Frame. Cada hoja del AUI_Notebook será una instanciación de la clase hoja.

Comenzamos...

Lo primero de todo es importar los módulos necesarios:

import wx
import wx.aui

A continuación diseñamos la clase que representará cada hoja de nuestro AUI_Notebook:

class hoja_notebook(wx.Panel):
    def __init__(self, parent, nombre_hoja):
        # Constructor.
        wx.Panel.__init__(self, parent)
        # Sizer.
        sizer = wx.BoxSizer(wx.VERTICAL)
        # Etiqueta.
        self.c0 = wx.StaticText(self, -1, nombre_hoja)
        # Cajas de texto.
        self.c1 = wx.TextCtrl(self, -1)
        self.c2 = wx.TextCtrl(self, -1)
        # Posicionamos las cajas de texto y la etiqueta en el sizer.
        sizer.Add(self.c0, 0, wx.EXPAND|wx.ALL,5)       
        sizer.Add(self.c1, 0, wx.EXPAND|wx.ALL,5)
        sizer.Add(self.c2, 0, wx.EXPAND|wx.ALL,5)
        # Añadimos el sizer al frame.
        self.SetSizer(sizer)

Esta clase hereda de un wx.Panel, por lo que es un panel. Vemos que dentro tiene un sizer vertical que posiciona una etiqueta y dos cajas de texto. En la instanciación de la clase pasamos el texto que se presentará en la etiqueta.

Bien, ahora crearemos el diseño de la clase frame que contendrá el AUI_Notebook y que contendrá hojas a través de la instanciación de la clase anterior.

class frame_principal(wx.Frame):
    def __init__(self, parent):
        # Constructor.
        wx.Frame.__init__(self, parent, title = "Trabajando con el AUI NoteBook")
        # Sizer.
        sizer = wx.BoxSizer(wx.VERTICAL)
        # Botón para obtener datos.
        self.boton = wx.Button(self, -1, "Devolver datos")
        # Incluimos el botón en el sizer.
        sizer.Add(self.boton, 0, wx.EXPAND|wx.ALL, 5)
        # Panel de NoteBook.
        self.panel = wx.aui.AuiNotebook(self, -1)
        # Hojas.
        hoja1 = hoja_notebook(self.panel, "Primera hoja")
        hoja2 = hoja_notebook(self.panel, "Segunda hoja")
        hoja3 = hoja_notebook(self.panel, "Tercera hoja")
        # Añadimos las hojas al NoteBook.
        self.panel.AddPage(hoja1, "Hoja 0")
        self.panel.AddPage(hoja2, "Hoja 1")
        self.panel.AddPage(hoja3, "Hoja 2")
        # Incluimos el panel en el sizer.
        sizer.Add(self.panel, 1, wx.EXPAND|wx.ALL, 5)
        # Y añadimos el sizer al frame.
        self.SetSizer(sizer)
        # Binding.
        self.boton.Bind(wx.EVT_BUTTON, self.OnClickBoton)

    # Manejador de eventos.    
    def OnClickBoton(self, event):
        # Hoja actual.
        hoja_actual = self.panel.GetSelection()
        # Número total de hojas.
        total_hojas = self.panel.GetPageCount()
        # Algo de información antes de buscar datos.
        cadena = "Este AUI NoteBook tiene %s hojas. Estás en la %s" % \
        (total_hojas,hoja_actual)
        wx.MessageBox(cadena,"Info",wx.OK)
        # Recorremos las hojas, obteniendo la información requerida.
        texto = ""
        for i in range(0,total_hojas):
            # Texto en la etiqueta de la hoja.
            texto_etiqueta = self.panel.GetPageText(i)  
            # Datos de las cajas de texto de la hoja i.
            dato1 = self.panel.GetPage(i).c1.GetValue()
            dato2 = self.panel.GetPage(i).c2.GetValue()
            # Info.
            texto += u'''
            La hoja número %s, con etiqueta "%s"
            contiene los datos:
            Caja de texto: %s
            Caja de texto: %s
            ''' % (i, texto_etiqueta, dato1, dato2)
        # Mostramos los datos por pantalla.
        wx.MessageBox(texto, "Datos", wx.OK)

Puff!. Vaya, esta clase es algo más larga. Pero no hay problema, la comentamos poco a poco, que es muy fácil de entender. Se puede decir que esta clase implementa la creación de hojas por una parte y el recorrido de dichas hojas a partir de la generación de un evento por hacer click en un botón. Bien, veámoslo por partes.

Esta clase hereda de wx.Frame, por lo que es un frame (una ventana típica de Windows).  En dicho frame se ha utilizado un sizer vertical para posicionar un botón (wx.Button) y un componente AUI_Notebook. Si vemos el código, justo después de instanciar el AUI_Notebook, instanciamos tres hojas del modo:

hojai = hoja_notebook(self.panel, "XXX hoja")

Esto es, hemos utilizado la clase hoja_notebook para crear 3 hojas. Darse cuenta que el padre de las hojas es el propio AUI_Notebook. Mediante el método AddPage se añaden las hojas. Además, se ha creado un binding para cuando se genere el evento de hacer click en el botón.

Dicho evento  (wx.EVT_BUTTON) lanza el manejador de eventos OnClickBoton, que se encargará de realizar el recorrido entre todas las hojas, así como mostrar información sobre el posicionamiento de las mismas. Mediante los métodos GetSelection() y GetPageText(i) se obtiene la hoja actual, así como el texto de la etiqueta.

Lo que se hace en realidad es recorrer todas las hojas y buscar la información entre los objetos de cajas de texto, mediante:

self.panel.GetPage(i).c1.GetValue()

Como el lector puede observar con GetPage se obtiene el objeto hoja_notebook. Únicamente hay que acceder a sus atributos (c1, c2) y con el método GetValue() (de wx.TextCtrl) se obtiene el texto que recoge.

El código para hacer funcionar este programa podría ser tal que así:
app = wx.PySimpleApp()
frame = frame_principal(None)
frame.Show()
app.MainLoop()

Veamos capturas del ejemplo para ver que efectivamente funciona...

Ejecutamos.


Incluimos datos.




Al hacer click en el botón "Devolver datos", teniendo en cuenta que estamos en la última hoja, tenemos...



 CONCLUSIONES

En este artículo hemos visto de una manera muy sencilla el componente AUI_Notebook, que podemos ver en más profundidad en la Demo de wxPython. Se ha creado una aplicación muy sencilla, que se compone de una clase de tipo wx.Panel que define una hoja y una clase wx.Frame que incluye un componente AUI_Notebook. Las hojas del AUI_Notebook son instanciaciones de la clase hoja que hemos creado. Además se han visto algunos métodos para acceder a las hojas, así como la manera de obtener los datos que un posible usuario hubiera incluido en las hojas.

Saludos.

No hay comentarios:

Publicar un comentario