martes, 19 de agosto de 2008

Lección 3

En esta lección crearemos un pequeño form que nos pedirá el nombre y la fecha de nacimiento y con estos datos calcularemos la edad y mostraremos un mensaje al pulsar un botón.

Utilizaremos los controles Edit text y Date Picker; igualmente haremos algunos cálculos, repasaremos algo de las lecciones anteriores.


LECCIÓN 3


Para esta lección crearemos una carpeta denominada nombre, igualmente crearemos un nuevo proyecto (File – New Project), seleccionamos WX_SDI_Python y guardamos el proyecto con el nombre de leccion3 dentro de la carpeta nombre.

Cargamos el frame MyFrame haciendo doble clic sobre éste.

Cambiamos su color de fondo, yo le he puesto un amarillo crema y como título de ventana le colocamos Mi lección No. 3.

Hasta el momento todo es repaso de la lección No. 2.

Antes de continuar, si deseamos que todos los controles que ubiquemos en el form tengan el mismo tipo y tamaño de fuente entonces procedemos de la siguiente manera:

Clic en cualquier parte del form
Luego, en la ficha propiedades buscas Font
Doble clic y la cambias por tu fuente preferida y el tamaño que deseas.

Yo he seleccionado Arial,11.

Colocamos en el form un Static Text y en la propiedad Name colocamos st_nombre y en la propiedad Text escribimos Nombre.

De la ficha Components hacemos doble clic en Edit Text, luego en la ficha propiedades y teniendo seleccionado el control que acabamos de ubicar en el form, cambiamos la propiedad Name por txt_nombre. Ampliamos un poco el control hacia la derecha para que nos quepa un nombre completo.

Ahora ubicamos otra etiqueta de texto (Static Text) que diga Fecha de nacimiento.

Para obtener algo como esto:


Ahora de la ficha Components buscamos el control denominado Date Picker, lo ubicamos en el form y le cambiamos la propiedad name a dp_fecnac (recuerda ponerle nombre a los controles que tengan referencia con su función o con su contenido, yo acostumbro a colocar las primeras letras que me indican qué tipo de control es separadas por un guión bajo del nombre que me identifica qué información contendrá o qué acción ejecutará).

Si el control una vez ubicado en el form no te corre con el mouse, selecciona el control de la ficha Project y veras como ahora sí puedes mover el control dentro del form.

Debajo de estos controles ubica un Static Text al que sólo le vas a cambiar la propiedad Name:st_mensaje

Por último ubica un botón (Button) cambia sus propiedades Name: bt_calcular y Text:Calcular Edad

Debes tener en pantalla algo parecido a esto:

Ahora procederemos a la programación.

Lo primero que haremos será que cuando el usuario acceda a nuestro programa el cursor se encuentre en el cuadro de texto Nombre, o sea, activaremos el foco inicial allí.

Esta es bien fácil. Haz clic en el txt_nombre o en el cuadro de texto que tienes frente a la palabra Nombre del form; luego en la ficha propiedades busca la propiedad Focus y cambiala de False a True haciendo doble clic sobre la palabra False. Y eso es todo.

Lo segundo es hacer que cuando el usuario presione la tecla enter el foco cambie al date picker y el nombre ingresado quede todo en mayúsculas.

¿Cómo lo hacemos?

Seleccionemos el cuadro de texto denominado txt_nombre, nos cambiamos a la ficha Events y activamos Base wxWidgets Events o como quien dice, hacemos clic en el botón B.

Activamos el evento EVT_KEY_DOWN (cuando se presione un tecla, normalmente se configura para que sea cuando se presione enter) y le asignamos un nombre a este evento, yo le he puesto va_fecha.

Hacemos clic en la ficha Python (la del centro debajo del form) y buscamos el evento que acabamos de asignar denominado va_fecha allí digitamos lo siguiente:


def va_fecha(self,event): #init function

#add your code here

n = self.txt_nombre.GetValue().upper()

key = event.GetKeyCode()

if (key==9 or key==13 or key==wx.WXK_NUMPAD_ENTER):

if n<>'':

self.txt_nombre.SetLabel(n)

self.dp_fecnac.SetFocus()

else:

dlg = wx.MessageDialog(self,"Debe ingresar el nombre","Faltan Datos",wx.OK | wx.ICON_ERROR)

dlg.ShowModal()

dlg.Destroy()

self.txt_nombre.SetFocus()

event.Skip()

return #end function

¿Qué es lo que acabamos de escribir?

En la línea 64 utilizamos un variable denominada n que nos recoge el valor del txt_nombre mediante el GetValue(), al final se observa upper(), esta palabra reservada es la que permite pasar el texto escrito a MAYÚSCULA.

En la línea 65 le asignamos a la variable key el evento GetKeyCode() que recoge el código -creo que ascii- de la tecla presionada.

En la línea 67 lo que hacemos es decirle a Python que si es presionada la tecla TAB (9) o la tecla ENTER (13) o la tecla ENTER del teclado numérico (wx.WXK_NUMPAD_ENTER) evalúe si la variable n se encuentra vacía n<>''.

Si la línea 68 es verdadera entonces, mediante la línea 69 cambiamos el texto a mayúscula y se cambia el foco al date picker dp_fecnac línea 70.

Si no se cumple la condición de la línea 68 entonces se muestra un mensaje de error y el foco vuelve a quedar en el txt_nombre.

Ahora vamos a programar el botón para que cuando éste sea pulsado nos calcule la edad del usuario.

Hacemos clic en el botón y nos pasamos a la ficha Events.

Seleccionamos Component Events o como quien dice, hacemos clic en el botón E.

Activamos el evento EVT_BUTTON (evento de botón) y le asignamos un nombre a la función, yo le he puesto calcular.

Clic en la pestaña Python y antes de buscar el nombre de la función que acabamos de configurar, debemos importar el módulo que maneja los formatos de tiempo y fecha:

En las primeras líneas debes entonces escribir:

import datetime

Justo en ese espacio, para que al ejecutar el programa no se te desaparezca.

Ahora sí buscamos nuestra función “calcular” y allí vamos a escribir:

def calcular(self,event): #init function

#add your code here

n = self.txt_nombre.GetValue()

fnace = self.dp_fecnac.GetValue().Format('%Y/%m/%d')

anio = fnace[:4]

mes = fnace[5:7]

dia = fnace[8:10]

nacim=datetime.date(int(anio),int(mes),int(dia))

dhoy=datetime.date.today()


edad=dhoy.year-nacim.year

if nacim.replace(year=dhoy.year):

edad -=1

e = edad+1

x = str(e)

self.st_mensaje.SetLabel(u'%s tu edad es de: %s años' % (n,x))

return #end function


Pero qué rayos es todo este cuento!!!

En la línea 52 tenemos una variable n que nos recoge el valor del txt_nombre

En la línea 53 tenemos una variable fnace que nos almacena la fecha ingresada (se supone que la de nacimiento) seguida por Format('%Y/%m/%d') que hace que la fecha ingresada quede con el formato de 4 dígitos en la fecha, dos en el mes y dos en el día, ejemplo: 1976/05/26, bueno puedes aprender más con la ayuda de Python.

En las líneas del 55 al 57 lo que estamos haciendo es almacenando parte de esa fecha en las variables anio, mes, día; me explico con el siguiente ejemplo:

Seleccione la fecha 1976/05/26; observa que anio tiene [:4] quiere decir que toma los valores que van desde el índice 0 (inclusive) hasta el 3 dígito, o sea, 1976; mes tiene [5:7] va desde el índice 5 (inclusive) hasta el 6 y por último tenemos día que va desde [8:10] aquí hay que agregar un número más a la cadena (10) ya que el operador de corte : ejecuta va hasta el j-1.

Para que tengas un poco más claro este concepto te recomiendo el tutorial Introducción a la programación con python de Andrés Marzal e Isabel Gracia, pág. 167 (Subcadenas: operador de corte). Excelente tutorial, lo que no recuerdo es de dónde me lo baje :(

Así ya recorde http://marmota.act.uji.es/MTP)

Bueno, continuo tratando de explicar (es que a veces yo no me entiendo pero sí sé lo que digo).

En la línea 59 utilizamos la variable nacim para almacenar el formato de fecha del datetime, razón por la cual en las primeras líneas teníamos que importar dicha clase, para poder utilizar sus propiedades más abajo.

Con la variable dhoy ubicada en la línea 60, obtenemos, perdón almacenamos la fecha de hoy en el formato yyyy-mm-dd o yyyy/mm/dd (realmente el separador – o / al final no es que importe mucho).

En la línea 62 con la variable edad lo que estamos haciendo realmente es restar el año actual con el año de la variable nacim o sea, el que ingresamos de nuestra fecha de nacimiento.

En la línea 63 hacemos un reemplazo de variable y una comparación, es para quitarle una unidad (línea 64) a la edad si el año de la edad dada es menor al año actual, sino (línea 65) le agrega una unidad.

En la línea 66 utilizamos una nueva variable x que convierte a la variable e en una cadena de texto para poderla ubicar dentro del st_mensaje.

Por último llega la línea 67 que mostrará el mensaje una vez se cumplan todas anteriores condiciones.

Al ejecutar el programa tenemos algo parecido a esto:

Bueno, eso es todo por hoy.

Mucha suerte a tod@s.

Y sería bueno que colocaran algún comentario quizás eso me anime más.

4 comentarios:

Peregrino dijo...

Hola Manuel, gracias por tu guía,te comento que con tu manual estoy empezando a trastear a Python, así que no te detengas que todo pinta que este manual sera de gran ayuda para iniciarse, hoy voy empezar tu tercer lección pero tengo una consulta, existe algún plugin como PyDEV para VisualMx, que te autocomplete la sintaxis?.

Saludos,

Rodolfo Arias
Heredia, Costa Rica.

Rafael dijo...

Hola Manuel,
Comparto la opinion del "Peregrino", estan realmente buenísimas las lecciones que cuelgas c/vez.
Mas bien queria hacer una observación: el if que estas haciendo en la función "calcular" te faltó colocar el terminante de la condición - osea los dos puntos (:) - por eso me estaba saliendo error y no levantaba el programa por varios minutos, hasta que me percate del caracter que faltaba.

if nacim.replace(year=dhoy.year):


Saludos

Rafael dijo...

Manuel,
Tube también un problema en la misma función calcular. Ahora fué en la sentencia donde seteas el valor a la etiqueta st_mensaje.
No levantaba mi programa con la línea que escribiste: self.st_mensaje.SetLabel(u'%s tu edad es de: %s años' % (n,x)).
Sólo me quedo editar esa línea y colocar lo siguiente:self.st_mensaje.SetLabel(n+' tu edad es de: '+x+' años').
Jojo, y con esto pudo levantar el programa, que extraño no??
Que crees que hice mal? o estaba mal la sintaxis???


Saludos.

Daneo dijo...

primero que todo gracias por este tuto,por otro lado le comento q el codigo correspondiente al EVT_DOWN.... no me funciono muy bien, ya que la plicación llama a la consola, pero no me ejecuta ninguna ventana, el problema esta en la línea if (key==9 or key==13 .....)
no se por que si ya me fije en los : al final del condicional, ahora para hacerlo funcional cumpliendo todas las condiciones excepto esa elimine la funcion va_fecha y agregue el codigo a calcular


def calcular(self,event): #init function
#[736]Code event VwX...Don't modify[736]#
#add your code here
n=self.tx_nombre.GetValue()
if n!='':
self.tx_nombre.SetLabel(n)
self.pd_fecnac.SetFocus()
fnace=self.pd_fecnac.GetValue().Format('%Y/%m/%d')
anio=fnace[:4]
mes=fnace[5:7]
dia=fnace[8:10]
nacim=datetime.date(int(anio),int(mes),int(dia))
dhoy=datetime.date.today()

edad=dhoy.year-nacim.year
if nacim.replace(year=dhoy.year):
edad-=1
e=edad+1
x=str(e)
self.st_mensaje.SetLabel(u'%s tu edad es de: %s años'%(n,x))
else:
self.st_mensaje.SetLabel('')
#self.st_nombre.Hide() #esconde
#self.st_nombre.Show()muestra
dlg=wx.MessageDialog(self,"Debe Ingresasr El Nombre","Faltan Datos",wx.OK|wx.ICON_ERROR)
dlg.ShowModal()
dlg.Destroy()
self.tx_nombre.SetFocus()

return #end function


asi si funciona sin problema alguno no se si sea la version de alguno de los componentes

python 2.5.4
xwpython 2.8 para python 25
visualwx 0.87_60

de resto seguiremos al tanto en el desarrollo del tutor y x q nop yo aportaria algo para el de boa-constructor.

suerte y gracias.