Eventos en un botón (wx.Button)

Los botones son componentes gráficos muy comunes que nos encontramos en cualquier interfaz de usuario y cuyo propósito es, generalmente, inicializar o confirmar un evento. En wxPython un botón ordinario se crea utilizando la clase wx.Button, a la cual habrán de pasarse como argumentos de inicialización mínimos, el objeto padre, un ID, y una cadena indicando la etiqueta visible del botón. 
Por ejemplo:

# -*- coding: utf-8 -*-
import wx

class TestFrame(wx.Frame):
def __init__(self,parent,title):
wx.Frame.__init__(self,parent=parent,title=title,size=(200,200))
self.boton = wx.Button(self, -1, u"Botón")
self.Centre(True)
self.Show()

if __name__=='__main__':
app = wx.App()
fr = TestFrame(None, "Test wxButton")
app.MainLoop()




Lo anterior crea un botón ocupando todo el espacio disponible en el Frame. Para colocar dos o más botones tendríamos que especificar el tamaño y posición de cada uno mediante los keyword argument size pos. Por ejemplo:

# -*- coding: utf-8 -*-
import wx

class TestFrame(wx.Frame):
def __init__(self,parent,title):
wx.Frame.__init__(self,parent=parent,title=title,size=(200,200))

self.boton1 = wx.Button(self, -1, u"Uno", size=(100,20),
pos=(50,10))
self.boton2 = wx.Button(self, -1, u"Dos", size=(100,20),
pos=(50,50))
self.boton3 = wx.Button(self, -1, u"Tres", size=(100,20),
pos=(50,90))

self.Centre(True)
self.Show()

if __name__=='__main__':
app = wx.App()
fr = TestFrame(None, "Test wxButton")
app.MainLoop()




Otra manera más conveniente de posicionar los botones o cualquier objeto gráfico sería utilizando sizers, de los cuales se estará hablando en posteriores entradas, pero vamos, que por ahora veremos cómo implementar manejo eventos en botones.

Así, en wxPython cuando se presiona un botón se lanza un evento del tipo wx.EVT_BUTTON, por ello lo que debemos hacer es utilizar el método Bind y agregar eventos de tipo wx.EVT_BUTTON al escuchador de eventos, asignando además un handler, que es básicamente una función o método que se encargará de manejar la respuesta de la interfaz al evento en cuestión.

Por ejemplo, vamos a imprimir un mensaje en consola cada vez que se presiona cualquiera de los tres botones que componen nuestra interfaz de usuario:

# -*- coding: utf-8 -*-
import wx

class TestFrame(wx.Frame):
def __init__(self,parent,title):
wx.Frame.__init__(self,parent=parent,title=title,size=(200,200))

self.boton1 = wx.Button(self, -1, u"Uno", size=(100,20),
pos=(50,10))
self.boton2 = wx.Button(self, -1, u"Dos", size=(100,20),
pos=(50,50))
self.boton3 = wx.Button(self, -1, u"Tres", size=(100,20),
pos=(50,90))
# Conectando evento
self.Bind(wx.EVT_BUTTON, self.OnClick)

self.Centre(True)
self.Show()

def OnClick(self,event):
print u"Has presionado un botón"


if __name__=='__main__':
app = wx.App()
fr = TestFrame(None, "Test wxButton")
app.MainLoop()

Note que hemos conectado los eventos de tipo wx.EVT_BUTTON al método OnClick que hace las veces de un handler. Luego, el método OnClick simplemente imprime en consola un mensaje.

Ahora, ¿cómo podríamos hacer que para cada botón presionado se tenga una respuesta diferente?. Hay dos formas comunes, a saber: especificando un handler para cada botón y utilizando el argumento eventpara identificar de dónde proviene el evento.

Primero vamos a utilizar un handler para cada botón. Debemos saber entonces que el método Bind acepta como tercer argumento un source o referencia a un objeto gráfico del cual se espera que provenga el evento. Algo como:

self.Bind(wx.EVT_BUTTON, self.OnClick, boton)

Pero vamos con el ejemplo que venimos trabajando:

# -*- coding: utf-8 -*-
import wx

class TestFrame(wx.Frame):
def __init__(self,parent,title):
wx.Frame.__init__(self,parent=parent,title=title,size=(200,200))

self.boton1 = wx.Button(self, -1, u"Uno", size=(100,20),
pos=(50,10))
self.boton2 = wx.Button(self, -1, u"Dos", size=(100,20),
pos=(50,50))
self.boton3 = wx.Button(self, -1, u"Tres", size=(100,20),
pos=(50,90))
# Conectando eventos
self.Bind(wx.EVT_BUTTON, self.OnClick1, self.boton1)
self.Bind(wx.EVT_BUTTON, self.OnClick2, self.boton2)
self.Bind(wx.EVT_BUTTON, self.OnClick3, self.boton3)

self.Centre(True)
self.Show()

def OnClick1(self,event):
print u"Has presionado el botón 1"

def OnClick2(self,event):
print u"Has presionado el botón 2"

def OnClick3(self,event):
print u"Has presionado el botón 3"


if __name__=='__main__':
app = wx.App()
fr = TestFrame(None, "Test wxButton")
app.MainLoop()

Como puede ver, por cada botón se conecta un evento wx.EVT_BUTTON con el handler correspondiente, así cada vez que se presione un botón diferente la respuesta obtenida será dependiendo del handler asignado.

Finalmente, la segunda forma consiste en utilizar el segundo parámetro del handler asignado para manejar un evento (normalmente y por convención llamado event). ¿Pero qué es el parámetro event?, en términos simples es un objeto de la clase wx.CommandEvent que contiene información acerca del evento lanzado. Implementando esta manera para el ejemplo anterior se tiene:

# -*- coding: utf-8 -*-
import wx

class TestFrame(wx.Frame):
def __init__(self,parent,title):
wx.Frame.__init__(self,parent=parent,title=title,size=(200,200))

self.boton1 = wx.Button(self, -1, u"Uno", size=(100,20),
pos=(50,10))
self.boton2 = wx.Button(self, -1, u"Dos", size=(100,20),
pos=(50,50))
self.boton3 = wx.Button(self, -1, u"Tres", size=(100,20),
pos=(50,90))
# Conectando eventos
self.Bind(wx.EVT_BUTTON, self.OnClick)

self.Centre(True)
self.Show()

def OnClick(self,event):
bt_label = event.GetEventObject().GetLabel()
print u"Has presionado el botón %s"%(bt_label)

if __name__=='__main__':
app = wx.App()
fr = TestFrame(None, "Test wxButton")
app.MainLoop()

El método GetEventObject del objeto event devuelve la referencia al objeto del cual proviene el evento, y posteriormente con el método GetLabel() se obtiene simplemente la etiqueta del botón correspondiente para imprimirla en pantalla.

Comentarios

Comments powered by Disqus