Diario
de un programador. Día 187
Moviendo
una figura en Python.
Es
el momento de ver cómo mover una figura en Python. Esto es algo que ya vimos en
su oportunidad en Small Basic, así que lo implementaremos aquí. Tk no es muy
potente para mover gráficos o realizar animaciones, por lo que aquí se verá
será algo sencillo (Ya llegaremos a algo más complejo con otra herramienta) que
servirá para tener una idea en cómo funciona esto de las animaciones.
En
el primer ejemplo, se mostrará cómo crear una esfera que se desplaza por la
ventana. Se empezará por crear la esfera y luego se procederá a moverla. El
siguiente código sirve para mostrar una esfera en pantalla.
from
tkinter import *
ventana
= Tk()
lienzo
= Canvas(ventana, width = 400, height = 400)
lienzo.pack()
lienzo.create_oval(10,10,50,50,
fill = "blue")
Ahora lo siguiente es agregar el código
que permita que la figura se mueva. El siguiente código es el encargado de
realizar esa tarea.
import time
from
tkinter import *
ventana
= Tk()
lienzo
= Canvas(ventana, width = 400, height = 400)
lienzo.pack()
lienzo.create_oval(10,10,50,50,
fill = "blue")
for x in range(0,60):
lienzo.move(1,5,0)
ventana.update()
time.sleep(0.05)
Como se puede ver, se ha agregado en la
primera línea una instrucción "import time", la cual permite utilizar
la función sleep, con la cual logramos controlar la velocidad en que se ejecuta
el programa. Para mover la figura, se utilizó una instrucción "for",
la cual genera un ciclo que va desde 0 a 59. La siguiente línea utiliza la
función "move". Esta función requiere de tres parámetros. El primero
se refiere al identificador de la figura. Cuando se crea una figura, esta
adquiere el identificador 1, si se crea otra adquiere el identificador 2 y así
sucesivamente. El siguiente parámetro se refiere al desplazamiento
"x" de la figura y el tercer parámetro se refiere al desplazamiento
"y" de la figura. En este caso, la función lienzo.move(1,5,0) quiere
decir "mover la figura con identificador 1, 5 pixeles a la derecha y 0
pixeles hacia abajo", como estamos dentro de un bucle "for",
entonces la figura se estará desplazando constantemente 5 pixeles hacia la
derecha hasta que finalice la instrucción.
La siguiente línea ventana.update(),
obliga a actualizar la ventana en cada ciclo. De no utilizar esta instrucción,
la ventana no se actualizaría sino hasta que finalice el bucle y no se vería el
efecto del movimiento ya que la figura se desplazaría directamente hacia su
posición final. La última línea time.sleep(0.05), permite que el programa se
ejecute más lento, con esto se logra apreciar el movimiento. Debido a que el
ciclo se ejecuta tan rápido que si no lo frenamos un poco entonces tampoco
veríamos su desplazamiento. Esta función, acepta como parámetro un número que
indica en cuantos milisegundos se debe retrasar
el programa.
La siguiente modificación al programa
anterior hará que la figura avance y retroceda constantemente. Esto se logró
mediante un ciclo while-True
import time
from tkinter import *
ventana = Tk()
lienzo = Canvas(ventana, width = 400,
height = 400)
lienzo.pack()
lienzo.create_oval(10,10,50,50,
fill = "blue")
while
True:
for x in range(0,60):
lienzo.move(1,5,0)
ventana.update()
time.sleep(0.05)
for x in range(0,60):
lienzo.move(1,-5,0)
ventana.update()
time.sleep(0.05)
Lo
siguiente a realizar es intentar mover la figura presionando una tecla. Para
poder hacer esto, es necesario crear un evento, los cuales trabajan mediante el
uso de funciones.
Entonces, vamos a modificar el primer
programa, ese que hacía que la figura se moviera por sí sola hacia la derecha.
Al borrarle algunas líneas el código quedaría de la siguiente manera:
from
tkinter import *
ventana
= Tk()
lienzo
= Canvas(ventana, width = 400, height = 400)
lienzo.pack()
lienzo.create_oval(10,10,50,50,
fill = "blue")
Como se puede ver, se eliminó la parte
que realizaba la animación, quedando solamente la parte correspondiente a la
creación de la figura.
Como se dijo antes, para manejar el
evento, es necesario crear una función. En este caso, la función se verá de la
siguiente manera:
def moverEsfera(evento):
lienzo.move(1,5,0)
La función a crear debe llevar un
argumento (puede ser cualquier palabra), este argumento le sirve al módulo Tk
para enviar información a la función. Para poder llamar a esta función, se
utiliza la función bind_all, la cual recibe dos argumentos. El primer argumento
es la tecla a presionar y el segundo parámetro corresponde a la función a
ejecutar. Por ejemplo, si quisiera que al presionar la tecla "Enter"
se ejecute la función "moverEsfera", la función bind_all debe quedar
de la siguiente manera:
bind_all("<Keypress-Return">,moverEsfera)
Llevando lo anterior al programa,
quedaría de la siguiente manera:
from
tkinter import *
def moverEsfera(evento):
lienzo.move(1,5,0)
ventana
= Tk()
lienzo
= Canvas(ventana, width = 400, height = 400)
lienzo.pack()
lienzo.create_oval(10,10,50,50,
fill = "blue")
lienzo.bind_all("<KeyPress-Return>",moverEsfera)
Si todo salió bien, entonces al
ejecutar el programa y presionar la tecla "Enter", la esfera debiera
de desplazarse hacia la derecha.
Para hacer que la figura se desplace en
otras direcciones, se pueden crear otras funciones para que cada función maneje
una tecla distinta y realice una operación distinta. Por ejemplo, podemos crear
cuatro funciones. Una función puede ser utilizada para mover la figura hacia
arriba, otra hacia abajo, etc. y que cada función sea llamada mediante una
tecla distinta. Esto podría quedar de la siguiente manera:
from tkinter
import *
def derecha(evento):
lienzo.move(1,5,0)
def izquierda(evento):
lienzo.move(1,-5,0)
def abajo(evento):
lienzo.move(1,0,5)
def arriba(evento):
lienzo.move(1,0,-5)
ventana
= Tk()
lienzo
= Canvas(ventana, width = 400, height = 400)
lienzo.pack()
lienzo.create_oval(10,10,50,50,
fill = "blue")
lienzo.bind_all("<KeyPress-Right>",derecha)
lienzo.bind_all("<KeyPress-Left>",izquierda)
lienzo.bind_all("<KeyPress-Down>",abajo)
lienzo.bind_all("<KeyPress-Up>",arriba)
Entonces, al ejecutar el programa, se
puede apreciar como la figura puede ser controlada con las flechas
direccionales del teclado.
Una alternativa a este programa lo
podemos lograr mediante el uso de la propiedad "keysym", la cual
permite manejar las teclas que se han pulsado.
Ejemplo:
from
tkinter import *
def
moverFigura(evento):
if evento.keysym == "Right":
lienzo.move(1,5,0)
elif evento.keysym == "Left":
lienzo.move(1,-5,0)
elif evento.keysym == "Down":
lienzo.move(1,0,5)
elif evento.keysym == "Up":
lienzo.move(1,0,-5)
ventana
= Tk()
lienzo
= Canvas(ventana, width = 400, height = 400)
lienzo.pack()
lienzo.create_oval(10,10,50,50,
fill = "blue")
lienzo.bind_all("<KeyPress-Right>",moverFigura)
lienzo.bind_all("<KeyPress-Left>",moverFigura)
lienzo.bind_all("<KeyPress-Down>",moverFigura)
lienzo.bind_all("<KeyPress-Up>",moverFigura)
Mediante el uso de keysym, solo se
trabaja en una función, que en este caso es "moverFigura".
Antes de seguir avanzando, quisiera
mencionar algunas funciones de uso común que nos harán la vida más fácil en más
de una ocasión.
FUNCIONES
INTERNAS
abs: La función abs retorna el valor absoluto de un
numero
ejemplo:
>>> abs(-15)
15
chr: Devuelve el carácter correspondiente al argumento ascii entregado
>>> chr(65)
'A'
float: Convierte un número entero o cadena en un número flotante o decimal
ejemplo:
>>> float(12)
12.0
>>> float("15")
15.0
int: Convierte un número flotante o cadena a número entero.
ejemplo:
>>> int(14.5)
14
>>> int("10")
10
len: Cuenta la cantidad de elementos de una lista o cadena(incluyendo
espacios).
ejemplo:
>>> len("Hola
mundo")
10
>>> lista = [1,2,3,4,5]
>>> len(lista)
5
max: Devuelve el elemento mayor de una lista o cadena
>>> lista = [1,2,3,4,5]
>>> max(lista)
5
>>> cadena = "abcde"
>>> max(cadena)
'e'
min: Devuelve el elemento menor de una lista o cadena
>>> lista = [1,2,3,4,5]
>>> min(lista)
1
>>> cadena = "abcde"
>>> min(cadena)
'a'
ord:
Regresa el equivalente ascii de un caracter
>>> ord("A")
65
pow:
Potencia de un número. El primer argumento es la base
mientras que el segundo es el exponente.
>>> pow(5,2)
25
round: Redondea un número decimal hacia abajo.
>>> round(14,1)
14
>>> round(14,9)
14
sorted: Ordena una lista de menor a mayor.
>>> numeros = [2,1,4,6,3,5]
>>> sorted(numeros)
[1, 2, 3, 4, 5, 6]
str: Convierte un número en una cadena.
>>> str(10)
'10'
>>>
sum: Suma los elementos de una lista
>>> lista = [1,2,3,4,5]
>>> sum(lista)
15
Esto es todo por ahora. Saludos
Gustavo J. Cerda Nilo
Noviembre 2016