wxPython - Guía rápida
wxPython es un contenedor de Python para wxWidgets(que está escrito en C ++), un popular kit de herramientas de GUI multiplataforma. Desarrollado por Robin Dunn junto con Harri Pasanen, wxPython se implementa como un módulo de extensión de Python.
Al igual que wxWidgets, wxPython también es un software gratuito. Se puede descargar desde el sitio web oficial.http://wxpython.org. Los binarios y el código fuente para muchas plataformas de sistemas operativos están disponibles para descargar en este sitio.
Los módulos principales en la API wxPython incluyen un módulo principal. Consiste enwxObjectclass, que es la base para todas las clases de la API. El módulo de control contiene todos los widgets utilizados en el desarrollo de aplicaciones GUI. Por ejemplo, wx.Button, wx.StaticText (análogo a una etiqueta), wx.TextCtrl (control de texto editable), etc.
La API wxPython tiene el módulo GDI (Interfaz de dispositivo gráfico). Es un conjunto de clases que se utilizan para dibujar en widgets. Clases como fuente, color, pincel, etc. son parte de él. Todas las clases de ventana de contenedor se definen en el módulo de Windows.
El sitio web oficial de wxPython también alberga Project Phoenix, una nueva implementación de wxPython para Python 3. *. Se centra en mejorar la velocidad, la capacidad de mantenimiento y la extensibilidad. El proyecto se inició en 2012 y aún se encuentra en fase beta.
Ventanas
Los binarios prediseñados para el sistema operativo Windows (tanto de 32 bits como de 64 bits) están disponibles en http://www.wxpython.org/download.phppágina. Las últimas versiones de los instaladores disponibles son: wxPython3.0-win32-3.0.2.0-py27.exe para Python 2.7 de 32 bits wxPython3.0-win64-3.0.2.0-py27.exe para Python 2.7 de 64 bits
La demostración de wxPython, las muestras y la documentación de wxWidgets también están disponibles para descargar en la misma página.
wxPython3.0-win32-docs-demos.exe
Linux
Los binarios de wxPython para muchas distribuciones de Linux se pueden encontrar en sus respectivos repositorios. Deberán usarse los administradores de paquetes correspondientes para descargar e instalar. Por ejemplo, en Debian Linux, el siguiente comando debería poder instalar wxPython.
sudo apt-get install python-wxgtk3.0
Mac OS
Los binarios precompilados para MacOS en forma de imágenes de disco están disponibles en la página de descarga del sitio web oficial.
Se crea una aplicación GUI simple que muestra el mensaje Hello World siguiendo los siguientes pasos:
Importar módulo wx.
Defina un objeto de la clase Aplicación.
Cree una ventana de nivel superior como objeto de la clase wx.Frame. Los parámetros de título y tamaño se dan en el constructor.
Aunque se pueden agregar otros controles en el objeto Frame, su diseño no se puede administrar. Por lo tanto, coloque un objeto Panel en el marco.
Agregue un objeto StaticText para mostrar 'Hola mundo' en la posición deseada dentro de la ventana.
Active la ventana de marco con el método show ().
Ingrese al bucle de eventos principal del objeto Aplicación.
import wx
app = wx.App()
window = wx.Frame(None, title = "wxPython Frame", size = (300,200))
panel = wx.Panel(window)
label = wx.StaticText(panel, label = "Hello World", pos = (100,50))
window.Show(True)
app.MainLoop()
El código anterior produce la siguiente salida:
wxFrame objectes la ventana de nivel superior más utilizada. Se deriva dewxWindow class. Un marco es una ventana cuyo tamaño y posición puede cambiar el usuario. Tiene una barra de título y botones de control. Si es necesario, se pueden habilitar otros componentes como la barra de menú, la barra de herramientas y la barra de estado. Una ventana wxFrame puede contener cualquier marco que no sea un diálogo u otro marco.
Crear una GUI de buen aspecto mediante la codificación manual puede ser tedioso. Una herramienta de diseño de GUI visual siempre es útil. Hay disponibles muchos IDE de desarrollo de GUI dirigidos a wxPython. A continuación se muestran algunos de ellos:
- wxFormBuilder
- wxDesigner
- wxGlade
- BoaConstructor
- gui2py
wxFormBuilderes un constructor de GUI WYSIWYG multiplataforma de código abierto que puede traducir el diseño de GUI wxWidget a formato C ++, Python, PHP o XML. Aquí se ofrece una breve introducción al uso de wxFormBuilder.
En primer lugar, debe descargar e instalar la última versión de wxFormBuilder desde http://sourceforge.net/projects/wxformbuilder/. Al abrir la aplicación, aparece un nuevo proyecto con un área gris en blanco en el centro.
Dé un nombre adecuado al proyecto y elija Python como lenguaje de generación de código. Esto se hace en la ventana de propiedades del objeto como se muestra en la siguiente imagen:
Luego, en la pestaña 'Formularios' de la paleta de componentes, elija Marco.
Agregue un wxBoxSizer vertical desde la pestaña 'Diseños'.
Agregue los controles necesarios en el cuadro con los subtítulos adecuados. Aquí, se agregan un StaticText (etiqueta), dos objetos TextCtrl (cuadros de texto) y un objeto wxButton. El marco se parece a la siguiente imagen:
Habilite Expandir y Estirar en estos tres controles. En las propiedades del objeto para el objeto wxButton, asigne una función findquare () al evento OnButtonClick.
Guarde el proyecto y presione F8 para generar código Python para la GUI desarrollada. Deje que el archivo generado se llame Demo.py
En el script Python ejecutable, importe demo.py y defina la función FindSquare (). Declare el objeto Aplicación e inicie un bucle de eventos principal. A continuación se muestra el código ejecutable:
import wx
#import the newly created GUI file
import demo
class CalcFrame(demo.MyFrame1):
def __init__(self,parent):
demo.MyFrame1.__init__(self,parent)
def FindSquare(self,event):
num = int(self.m_textCtrl1.GetValue())
self.m_textCtrl2.SetValue (str(num*num))
app = wx.App(False)
frame = CalcFrame(None)
frame.Show(True)
#start the applications
app.MainLoop()
El código anterior produce la siguiente salida:
Los wxWidgets originales (escritos en C ++) son una biblioteca de clases enorme. Las clases de GUI de esta biblioteca se migran a Python con el módulo wxPython, que intenta reflejar la biblioteca wxWidgets original lo más cerca posible. Entonces, la clase wx.Frame en wxPython actúa de la misma manera que la clase wxFrame en su versión C ++.
wxObject es la base para la mayoría de las clases. Un objeto de wxApp (wx.App en wxPython) representa la propia aplicación. Después de generar la GUI, la aplicación ingresa en un bucle de eventos mediante el método MainLoop (). Los siguientes diagramas representan la jerarquía de clases de las clases de GUI más comúnmente utilizadas incluidas en wxPython.
SN | Clases y descripción |
---|---|
1 | wx.Frame La clase wx.Frame tiene un constructor predeterminado sin argumentos. |
2 | wx.Panel La clase wx.Panel generalmente se coloca dentro de un objeto wxFrame. Esta clase también se hereda de la clase wxWindow. |
3 | wx.StaticText El objeto de clase wx.StaticText presenta un control que contiene dicho texto de solo lectura. Puede denominarse control pasivo ya que no produce ningún evento. |
4 | TextCtrl En wxPython, un objeto de la clase wx.TextCtrl sirve para este propósito. Es un control en el que se puede visualizar y editar el texto. |
5 | RadioButton y RadioBox Cada botón, un objeto de la clase wx.RadioButton lleva una etiqueta de texto junto a un botón redondo. La API de wxPython también consta de la clase wx.RadioBox. Su objeto ofrece un borde y una etiqueta al grupo. |
6 | wx.CheckBox Una casilla de verificación muestra una pequeña caja rectangular etiquetada. Cuando se hace clic, aparece una marca de verificación dentro del rectángulo para indicar que se hizo una elección. |
7 | ComboBox y clase de elección Un objeto wx.ComboBox presenta una lista de elementos para seleccionar. Se puede configurar para que sea una lista desplegable o con visualización permanente. La API wxPython contiene una clase wx.Choice, cuyo objeto también es una lista desplegable, que es permanentemente de solo lectura. |
8 | Wx.Gauge El objeto de clase Wx.Gauge muestra una barra vertical u horizontal, que muestra gráficamente la cantidad en aumento. |
9 | wx.Slider La API wxPython contiene la clase wx.Slider. Ofrece la misma funcionalidad que la de Scrollbar. Slider ofrece una forma conveniente de controlar el arrastre del controlador mediante el deslizador de eventos wx.EVT_SLIDER específico. |
10 | wx.MenuBar Una barra horizontal justo debajo de la barra de título de una ventana de nivel superior está reservada para mostrar una serie de menús. Es un objeto de la clase wx.MenuBar en la API wxPython. |
11 | wx.Toolbar Si el parámetro de estilo del objeto wx.Toolbar se establece en wx.TB_DOCKABLE, se puede acoplar. También se puede construir una barra de herramientas flotante usando la clase AUIToolBar de wxPython. |
12 | Wx.Dialog Aunque un objeto de la clase Dialog aparece como un marco, normalmente se usa como una ventana emergente en la parte superior de un marco principal. El objetivo de un diálogo es recopilar algunos datos del usuario y enviarlos al marco principal. |
13 | wx.Notebook wx.El widget de cuaderno presenta un control con pestañas. Un objeto Notebook en un marco tiene una o más pestañas (llamadas Páginas), cada una de ellas con un panel que muestra el diseño de los controles. |
14 | wx.SplitterWindow El objeto de esta clase es un administrador de diseño, que contiene dos subventanas cuyo tamaño se puede cambiar dinámicamente arrastrando los límites entre ellas. El control Splitter proporciona un controlador que se puede arrastrar para cambiar el tamaño de los controles. |
15 | HTMLWindow La biblioteca wxHTML contiene clases para analizar y mostrar contenido HTML. Aunque no se pretende que sea un navegador con todas las funciones, el objeto wx.HtmlWindow es un visor HTML genérico. |
dieciséis | ListBox y ListCtrl Un widget wx.ListBox presenta una lista de cadenas desplazable verticalmente. De forma predeterminada, se puede seleccionar un solo elemento de la lista. El widget ListCtrl es una herramienta de selección y visualización de listas altamente mejorada. La lista de más de una columna se puede mostrar en la vista Informe, la vista Lista o la vista Icono. |
A diferencia de una aplicación en modo de consola, que se ejecuta de manera secuencial, una aplicación basada en GUI está impulsada por eventos. Las funciones o métodos se ejecutan en respuesta a las acciones del usuario, como hacer clic en un botón, seleccionar un elemento de la colección o hacer clic con el mouse, etc., llamados eventos.
Los datos pertenecientes a un evento que tiene lugar durante el tiempo de ejecución de la aplicación se almacenan como objeto de una subclase derivada de wx.Event. Un control de visualización (como Button) es la fuente de un evento de un tipo particular y produce un objeto de la clase Event asociado a él. Por ejemplo, al hacer clic en un botón se emite un wx.CommandEvent. Estos datos de eventos se envían al método controlador de eventos en el programa. wxPython tiene muchas carpetas de eventos predefinidas. UnEvent binder encapsula la relación entre un widget específico (control), su tipo de evento asociado y el método del controlador de eventos.
Por ejemplo, para llamar OnClick() method del programa en el evento de clic de un botón, se requiere la siguiente declaración:
self.b1.Bind(EVT_BUTTON, OnClick)
Bind() methodes heredado por todos los objetos de visualización de la clase wx.EvtHandler. EVT_.BUTTON aquí es la carpeta, que asocia el evento de clic de botón al método OnClick ().
Ejemplo
En el siguiente ejemplo, MoveEvent, causado al arrastrar la ventana de nivel superior, un objeto wx.Frame en este caso, está conectado a OnMove() methodutilizando el cuaderno wx.EVT_MOVE. El código muestra una ventana. Si se mueve con el mouse, sus coordenadas instantáneas se muestran en la consola.
import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_MOVE, self.OnMove)
self.SetSize((250, 180))
self.SetTitle('Move event')
self.Centre()
self.Show(True)
def OnMove(self, e):
x, y = e.GetPosition()
print "current window position x = ",x," y= ",y
ex = wx.App()
Example(None)
ex.MainLoop()
El código anterior produce la siguiente salida:
posición actual de la ventana x = 562 y = 309
posición actual de la ventana x = 562 y = 309
posición actual de la ventana x = 326 y = 304
posición actual de la ventana x = 384 y = 240
posición actual de la ventana x = 173 y = 408
posición actual de la ventana x = 226 y = 30
posición actual de la ventana x = 481 y = 80
Algunas de las subclases heredadas de wx.Event se enumeran en la siguiente tabla:
SN | Eventos y descripción |
---|---|
1 | wxKeyEvent Ocurre cuando se presiona o suelta una tecla |
2 | wxPaintEvent Se genera siempre que sea necesario volver a dibujar el contenido de la ventana. |
3 | wxMouseEvent Contiene datos sobre cualquier evento debido a la actividad del mouse, como el botón del mouse presionado o arrastrado |
4 | wxScrollEvent Asociado con controles desplazables como wxScrollbar y wxSlider |
5 | wxCommandEvent Contiene datos de eventos que se originan en muchos widgets, como botones, cuadros de diálogo, portapapeles, etc. |
6 | wxMenuEvent Diferentes eventos relacionados con el menú, excepto el clic del botón de comando del menú |
7 | wxColourPickerEvent Eventos generados por wxColourPickerCtrl |
8 | wxDirFilePickerEvent Eventos generados por FileDialog y DirDialog |
Los eventos en wxPython son de dos tipos. Eventos básicos y eventos de comando. Un evento básico permanece local a la ventana en la que se origina. La mayoría de los wxWidgets generan eventos de comando. UNcommand event se puede propagar a la ventana o ventanas, que están por encima de la ventana de origen en la jerarquía de clases.
Ejemplo
A continuación se muestra un ejemplo sencillo de propagación de eventos. El código completo es:
import wx
class MyPanel(wx.Panel):
def __init__(self, parent):
super(MyPanel, self).__init__(parent)
b = wx.Button(self, label = 'Btn', pos = (100,100))
b.Bind(wx.EVT_BUTTON, self.btnclk)
self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)
def OnButtonClicked(self, e):
print 'Panel received click event. propagated to Frame class'
e.Skip()
def btnclk(self,e):
print "Button received click event. propagated to Panel class"
e.Skip()
class Example(wx.Frame):
def __init__(self,parent):
super(Example, self).__init__(parent)
self.InitUI()
def InitUI(self):
mpnl = MyPanel(self)
self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)
self.SetTitle('Event propagation demo')
self.Centre()
self.Show(True)
def OnButtonClicked(self, e):
print 'click event received by frame class'
e.Skip()
ex = wx.App()
Example(None)
ex.MainLoop()
En el código anterior, hay dos clases. MyPanel, una subclase wx.Panel y Ejemplo, una subclase wx.Frame que es la ventana de nivel superior para el programa. Se coloca un botón en el panel.
Este objeto Button está vinculado a un controlador de eventos btnclk () que lo propaga a la clase principal (MyPanel en este caso). El clic del botón genera unCommandEvent que se puede propagar a su padre mediante el método Skip ().
El objeto de clase MyPanel también vincula el evento recibido a otro controlador OnButtonClicked (). Esta función a su vez transmite a su padre, la clase Example. El código anterior produce la siguiente salida:
Button received click event. Propagated to Panel class.
Panel received click event. Propagated to Frame class.
Click event received by frame class.
Un widget GUI se puede colocar dentro de la ventana del contenedor especificando sus coordenadas absolutas medidas en píxeles. Las coordenadas son relativas a las dimensiones de la ventana definidas por el argumento de tamaño de su constructor. La posición del widget dentro de la ventana está definida porpos argumento de su constructor.
import wx
app = wx.App()
window = wx.Frame(None, title = "wxPython Frame", size = (300,200))
panel = wx.Panel(window)
label = wx.StaticText(panel, label = "Hello World", pos = (100,50))
window.Show(True)
app.MainLoop()
Esta Absolute Positioning sin embargo, no es adecuado debido a las siguientes razones:
La posición del widget no cambia incluso si se cambia el tamaño de la ventana.
Es posible que la apariencia no sea uniforme en diferentes dispositivos de visualización con diferentes resoluciones.
La modificación en el diseño es difícil, ya que puede ser necesario rediseñar todo el formulario.
La API wxPython proporciona clases de diseño para una gestión más elegante del posicionamiento de los widgets dentro del contenedor. Las ventajas de los administradores de diseño sobre el posicionamiento absoluto son:
- Los widgets dentro de la ventana cambian de tamaño automáticamente.
- Garantiza una apariencia uniforme en dispositivos de visualización con diferentes resoluciones.
- Es posible agregar o eliminar widgets dinámicamente sin tener que rediseñar.
El administrador de diseño se llama Sizer en wxPython. Wx.Sizer es la clase base para todas las subclases de dimensionadores. Analicemos algunos de los medidores importantes, como wx.BoxSizer, wx.StaticBoxSizer, wx.GridSizer, wx.FlexGridSizer y wx.GridBagSizer.
SN | Medidores y descripción |
---|---|
1 | BoxSizer Este medidor permite que los controles se organicen en filas o columnas. El diseño de BoxSizer está determinado por su argumento de orientación (ya sea wxVERTICAL o wxHORIZONTAL). |
2 | GridSizer Como sugiere el nombre, un objeto GridSizer presenta una cuadrícula bidimensional. Los controles se agregan en la ranura de la cuadrícula en orden de izquierda a derecha y de arriba a abajo. |
3 | FlexiGridSizer Este medidor también tiene una cuadrícula bidimensional. Sin embargo, proporciona un poco más de flexibilidad en la disposición de los controles en las celdas. |
4 | GridBagSizer GridBagSizer es un medidor versátil. Ofrece más mejoras que FlexiGridSizer. El widget secundario se puede agregar a una celda específica dentro de la cuadrícula. |
5 | StaticBoxSizer Un StaticBoxSizer coloca un medidor de caja en una caja estática. Proporciona un borde alrededor de la caja junto con una etiqueta en la parte superior. |
El widget de botón se usa más ampliamente en cualquier interfaz GUI. Captura el evento de clic generado por el usuario. Su uso más obvio es activar una función de controlador vinculada a él.
La biblioteca de clases wxPython proporciona diferentes tipos de botones. Hay un botón simple y tradicional,wx.Buttonobjeto de clase, que lleva un texto como título. También está disponible un botón de dos estados, que se denominawx.ToggleButton. Su estado presionado o deprimido se puede identificar mediante la función de manejador de eventos.
Otro tipo de botón, wx.BitmapButton muestra un mapa de bits (imagen) como icono en su cara.
El constructor para la clase wx.Button y la clase wx.ToggleButton toma los siguientes argumentos:
Wx.Button(parent, id, label, pos, size, style)
Estos son algunos métodos importantes de la clase wx.Button:
SN | Métodos y descripción |
---|---|
1 | SetLabel() Establece el título del botón mediante programación |
2 | GetLabel() Devuelve el título del botón. |
3 | SetDefault() El botón está configurado por defecto para la ventana de nivel superior. Emula el evento de clic al presionar la tecla Enter |
Dos métodos importantes de la clase wx.ToggleButton son:
SN | Métodos y descripción |
---|---|
1 | GetValue() Devuelve el estado del botón de alternancia (encendido / apagado) |
2 | SetValue() Establece el estado del botón mediante programación |
Para crear un botón de mapa de bits, en primer lugar, es necesario construir un objeto de mapa de bits a partir de un archivo de imagen.
La siguiente variación del constructor de clase wx.Bitmap es la más utilizada:
Wx.Bitmap(fiiename, wx.BITMAP_TYPE)
Algunas de las constantes de tipo de mapa de bits predefinidas son:
wx.BITMAP_TYPE_BMP |
wx.BITMAP_TYPE_ICO |
wx.BITMAP_TYPE_CUR |
wx.BITMAP_TYPE_TIFF |
wx.BITMAP_TYPE_TIF |
wx.BITMAP_TYPE_GIF |
wx.BITMAP_TYPE_PNG |
wx.BITMAP_TYPE_JPEG |
wx.BITMAP_TYPE_PCX |
wx.BITMAP_TYPE_ICON |
wx.BITMAP_TYPE_ANY |
Este objeto de mapa de bits se utiliza como uno de los parámetros del constructor de la clase wx.BitmapButton.
Wx.BitmapButton(parent, id, bitmap, pos, size, style)
En algunas plataformas de SO, el botón de mapa de bits puede mostrar tanto el mapa de bits como la etiqueta. Los métodos SetLabel () asignan el título. En otras plataformas, sirve como etiqueta interna.
El botón normal y el botón de mapa de bits emite un wx.CommandEvent. El enlazador EVT_BUTTON le asocia una función de controlador.
El botón de alternancia, por otro lado, utiliza la carpeta wx.TOGGLEBUTTON para el manejo de eventos.
En el siguiente ejemplo, los botones de los tres tipos se colocan en un medidor de cuadro vertical de un panel.
El objeto de botón simple se crea usando la declaración -
self.btn = wx.Button(panel, -1, "click Me")
El botón de alternancia se construye con la siguiente declaración:
self.tbtn = wx.ToggleButton(panel , -1, "click to on")
Estos botones se agregan al medidor vertical usando las siguientes declaraciones:
vbox.Add(self.btn,0,wx.ALIGN_CENTER)
vbox.Add(self.tbtn,0,wx.EXPAND|wx.ALIGN_CENTER)
Note - Debido a la bandera wx.EXPAND, el botón de alternancia ocupa todo el ancho del marco.
Al utilizar los binders EVT_BUTTON y EVT_TOGGLEBUTTON, se asocian con los respectivos controladores.
self.btn.Bind(wx.EVT_BUTTON,self.OnClicked)
self.tbtn.Bind(wx.EVT_TOGGLEBUTTON,self.OnToggle)
Se agregan tres botones de mapa de bits en un medidor de cuadro horizontal. Estos botones muestran una imagen como icono como título.
bmp = wx.Bitmap("NEW.BMP", wx.BITMAP_TYPE_BMP)
self.bmpbtn = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp,
size = (bmp.GetWidth()+10, bmp.GetHeight()+10))
bmp1 = wx.Bitmap("OPEN.BMP", wx.BITMAP_TYPE_BMP)
self.bmpbtn1 = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp1,
size = (bmp.GetWidth()+10, bmp.GetHeight()+10))
bmp2 = wx.Bitmap("SAVE.BMP", wx.BITMAP_TYPE_BMP)
self.bmpbtn2 = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp2,
size = (bmp.GetWidth()+10, bmp.GetHeight()+10))
El evento de clic de estos tres botones se dirige al método OnClicked ().
self.bmpbtn.Bind(wx.EVT_BUTTON, self.OnClicked)
self.bmpbtn1.Bind(wx.EVT_BUTTON, self.OnClicked)
self.bmpbtn2.Bind(wx.EVT_BUTTON, self.OnClicked)
Las etiquetas internas de estos botones están configuradas como NUEVO, ABRIR y GUARDAR respectivamente.
La función del controlador de eventos OnClicked () recupera la etiqueta del botón de origen, que provocó el evento de clic. Esa etiqueta está impresa en la consola.
def OnClicked(self, event):
btn = event.GetEventObject().GetLabel()
print "Label of pressed button = ",btn
El controlador de eventos OnToggle () se activa cuando se hace clic en el botón de alternancia. Su estado se lee mediante el método GetValue () y, en consecuencia, se establece el título del botón.
def OnToggle(self,event):
state = event.GetEventObject().GetValue()
if state == True:
print "off"
event.GetEventObject().SetLabel("click to off")
else:
print "on"
event.GetEventObject().SetLabel("click to on")
La lista completa de códigos es la siguiente:
import wx
class Mywin(wx.Frame):
def __init__(self, parent, title):
super(Mywin, self).__init__(parent, title = title,size = (200,150))
panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
self.btn = wx.Button(panel,-1,"click Me")
vbox.Add(self.btn,0,wx.ALIGN_CENTER)
self.btn.Bind(wx.EVT_BUTTON,self.OnClicked)
self.tbtn = wx.ToggleButton(panel , -1, "click to on")
vbox.Add(self.tbtn,0,wx.EXPAND|wx.ALIGN_CENTER)
self.tbtn.Bind(wx.EVT_TOGGLEBUTTON,self.OnToggle)
hbox = wx.BoxSizer(wx.HORIZONTAL)
bmp = wx.Bitmap("NEW.BMP", wx.BITMAP_TYPE_BMP)
self.bmpbtn = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp,
size = (bmp.GetWidth()+10, bmp.GetHeight()+10))
hbox.Add(self.bmpbtn,0,wx.ALIGN_CENTER)
self.bmpbtn.Bind(wx.EVT_BUTTON,self.OnClicked)
self.bmpbtn.SetLabel("NEW")
bmp1 = wx.Bitmap("OPEN.BMP", wx.BITMAP_TYPE_BMP)
self.bmpbtn1 = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp1,
size = (bmp.GetWidth()+10, bmp.GetHeight()+10))
hbox.Add(self.bmpbtn1,0,wx.ALIGN_CENTER)
self.bmpbtn1.Bind(wx.EVT_BUTTON,self.OnClicked)
self.bmpbtn1.SetLabel("OPEN")
bmp2 = wx.Bitmap("SAVE.BMP", wx.BITMAP_TYPE_BMP)
self.bmpbtn2 = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp2,
size = (bmp.GetWidth()+10, bmp.GetHeight()+10))
hbox.Add(self.bmpbtn2,0,wx.ALIGN_CENTER)
self.bmpbtn2.Bind(wx.EVT_BUTTON,self.OnClicked)
self.bmpbtn2.SetLabel("SAVE")
vbox.Add(hbox,1,wx.ALIGN_CENTER)
panel.SetSizer(vbox)
self.Centre()
self.Show()
self.Fit()
def OnClicked(self, event):
btn = event.GetEventObject().GetLabel()
print "Label of pressed button = ",btn
def OnToggle(self,event):
state = event.GetEventObject().GetValue()
if state == True:
print "Toggle button state off"
event.GetEventObject().SetLabel("click to off")
else:
print " Toggle button state on"
event.GetEventObject().SetLabel("click to on")
app = wx.App()
Mywin(None, 'Button demo')
app.MainLoop()
El código anterior produce la siguiente salida:
Etiqueta del botón presionado = haz clic en mí
Desactivar el estado del botón
Activar el estado del botón
Etiqueta del botón pulsado = NUEVO
Etiqueta del botón pulsado = ABRIR
Etiqueta del botón pulsado = GUARDAR
wxAuies una biblioteca de interfaz de usuario avanzada incorporada en la API wxWidgets. Wx.aui.AuiManager la clase central en el marco AUI.
AuiManageradministra los paneles asociados con un marco particular utilizando la información de cada panel en el objeto wx.aui.AuiPanelInfo. Aprendamos sobre varias propiedades del comportamiento flotante y de acoplamiento del control de objetos PanelInfo.
Colocar ventanas empotrables en el marco del nivel superior implica los siguientes pasos:
Primero, cree un objeto AuiManager.
self.mgr = wx.aui.AuiManager(self)
Luego, se diseña un panel con los controles necesarios.
pnl = wx.Panel(self)
pbox = wx.BoxSizer(wx.HORIZONTAL)
text1 = wx.TextCtrl(pnl, -1, "Dockable", style = wx.NO_BORDER | wx.TE_MULTILINE)
pbox.Add(text1, 1, flag = wx.EXPAND)
pnl.SetSizer(pbox)
Se establecen los siguientes parámetros de AuiPanelInfo.
Direction - Arriba, Abajo, Izquierda, Derecha o Centro
Position- Se puede colocar más de un panel dentro de una región acoplable. A cada uno se le asigna un número de posición.
Row- Aparece más de un panel en una fila. Al igual que aparece más de una barra de herramientas en la misma fila.
Layer - Los paneles se pueden colocar en capas.
Con este PanelInfo, el panel diseñado se agrega al objeto administrador.
info1 = wx.aui.AuiPaneInfo().Bottom()
self.mgr.AddPane(pnl,info1)
El resto de la ventana de nivel superior puede tener otros controles como de costumbre.
El código completo es el siguiente:
import wx
import wx.aui
class Mywin(wx.Frame):
def __init__(self, parent, title):
super(Mywin, self).__init__(parent, title = title, size = (300,300))
self.mgr = wx.aui.AuiManager(self)
pnl = wx.Panel(self)
pbox = wx.BoxSizer(wx.HORIZONTAL)
text1 = wx.TextCtrl(pnl, -1, "Dockable", style = wx.NO_BORDER | wx.TE_MULTILINE)
pbox.Add(text1, 1, flag = wx.EXPAND)
pnl.SetSizer(pbox)
info1 = wx.aui.AuiPaneInfo().Bottom()
self.mgr.AddPane(pnl, info1)
panel = wx.Panel(self)
text2 = wx.TextCtrl(panel, size = (300,200), style = wx.NO_BORDER | wx.TE_MULTILINE)
box = wx.BoxSizer(wx.HORIZONTAL)
box.Add(text2, 1, flag = wx.EXPAND)
panel.SetSizerAndFit(box)
self.mgr.Update()
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Centre()
self.Show(True)
def OnClose(self, event):
self.mgr.UnInit()
self.Destroy()
app = wx.App()
Mywin(None,"Dock Demo")
app.MainLoop()
El código anterior produce la siguiente salida:
Una aplicación de GUI típica puede tener varias ventanas. Los widgets con pestañas y apilados permiten activar una de esas ventanas a la vez. Sin embargo, muchas veces este enfoque puede no ser útil ya que la vista de otras ventanas está oculta.
Una forma de mostrar varias ventanas simultáneamente es crearlas como ventanas independientes. Esto se llama SDI (Single Document Interface). Esto requiere más recursos de memoria ya que cada ventana puede tener su propio sistema de menú, barra de herramientas, etc.
El marco MDI en wxPython proporciona una clase wx.MDIParentFrame. Su objeto actúa como un contenedor para múltiples ventanas secundarias, cada una de las cuales es un objeto de la clase wx.MDIChildFrame.
Las ventanas secundarias residen en el área MDIClientWindow del marco principal. Tan pronto como se agrega un marco secundario, la barra de menú del marco principal muestra un menú Ventana que contiene botones para organizar los elementos secundarios en cascada o en mosaico.
Ejemplo
El siguiente ejemplo ilustra los usos de MDIParentFrame como ventana de nivel superior. Un botón de menú llamado NewWindow agrega una ventana secundaria en el área del cliente. Se pueden agregar varias ventanas y luego organizarlas en cascada o en mosaico.
El código completo es el siguiente:
import wx
class MDIFrame(wx.MDIParentFrame):
def __init__(self):
wx.MDIParentFrame.__init__(self, None, -1, "MDI Parent", size = (600,400))
menu = wx.Menu()
menu.Append(5000, "&New Window")
menu.Append(5001, "&Exit")
menubar = wx.MenuBar()
menubar.Append(menu, "&File")
self.SetMenuBar(menubar)
self.Bind(wx.EVT_MENU, self.OnNewWindow, id = 5000)
self.Bind(wx.EVT_MENU, self.OnExit, id = 5001)
def OnExit(self, evt):
self.Close(True)
def OnNewWindow(self, evt):
win = wx.MDIChildFrame(self, -1, "Child Window")
win.Show(True)
app = wx.App()
frame = MDIFrame()
frame.Show()
app.MainLoop()
El código anterior produce la siguiente salida:
GDI+ (Interfaz de dibujo de gráficos), CoreGraphics y Cairo librariesforman el marco de dibujo API en wxPython. wx.GraphicsContext es el objeto principal que se puede dibujar, mediante el cual se crean varios objetos de contexto de dispositivo.
wx.DC es una clase abstracta. Sus clases derivadas se utilizan para representar gráficos y texto en diferentes dispositivos. Las clases de contexto de dispositivo son:
wx.ScreenDC - Use esto para pintar en la pantalla, a diferencia de una ventana individual.
wx.ClientDC - Use esto para pintar en el área del cliente de la ventana (la parte sin bordes y otras decoraciones), pero no lo use desde dentro de un wxPaintEvent.
wx.PaintDC- Use esto para pintar en el área del cliente de la ventana, pero solo desde dentro de un wxPaintEvent.
wx.WindowDC- Use esto para pintar en toda el área de la ventana, incluidas las decoraciones. Es posible que esto no esté disponible en plataformas que no sean de Windows.
La API de dibujo de wxPython ofrece diferentes funciones para dibujar formas, texto e imágenes. Los objetos necesarios para dibujar, como Color, Pluma, Pincel y Fuente también se pueden construir usando clases GDI.
wx.Colour Class
El objeto de color representa una combinación de valores de intensidad RGB (ROJO, Verde y Azul), cada uno en la escala de 0-255. Hay algunos objetos de color predefinidos como:
- wxBLACK
- wxBLUE
- wxCYAN
- wxGREEN
- wxYELLOW
- wxLIGHT_GREY
- wxRED
- wxWHITE
El color con combinación personalizada de valores RGB se forma como wx.Colour object.
wx.Colour(r,g,b)
wx.Pen Clase
El objeto de lápiz determina el color, el ancho y el estilo de la forma de los gráficos como líneas, rectángulos, círculos, etc.
Predefined Pen objects son -
wxBLACK_DASHED_PEN |
wxBLACK_PEN |
wxBLUE_PEN |
wxCYAN_PEN |
wxGREEN_PEN |
wxYELLOW_PEN |
wxGREY_PEN |
wxLIGHT_GREY_PEN |
wxMEDIUM_GREY_PEN |
wxRED_PEN |
wxTRANSPARENT_PEN |
wxWHITE_PEN |
Predefined Pen styles son -
wx.SOLID |
wx.DOT |
wx.LONG_DASH |
wx.SHORT_DASH |
wx.DOT_DASH |
wx.TRANSPARENT |
wx.Brush Class
El pincel es otro objeto gráfico elemental necesario para rellenar los fondos de formas como rectángulos, elipses, círculos, etc.
Un objeto Brush personalizado requiere los parámetros de estilo wx.Colour y Brush. La siguiente es una lista de estilos de pincel predefinidos:
wx.SOLID |
ANCHO. |
wx.BDIAGONAL_HATCH |
wx.CROSSDIAG_HATCH |
wx.FDIAGONAL_HATCH |
wx.CROSS_HATCH |
wx.HORIZONTAL_HATCH |
wx.VERTICAL_HATCH |
wx.TRANSPARENT |
wxPython tiene una serie de funciones que facilitan el dibujo de diferentes formas, texto e imágenes.
SN | Funciones y descripción |
---|---|
1 | DrawRectangle() Dibuja un rectángulo de dimensiones dadas |
2 | DrawCircle() Dibuja un círculo en el punto dado como centro y radio |
3 | DrawEllipse() Dibuja una elipse con el radio xey dado |
4 | DrawLine() Dibuja una línea entre dos objetos wx.Point |
5 | DrawBitmap() Dibuja una imagen en la posición dada |
6 | DrawText() Muestra el texto dado en la posición especificada |
Ejemplo
Las funciones anteriores se implementan en el siguiente ejemplo, haciendo uso de los objetos Pluma, Pincel, Color y Fuente.
El código completo es el siguiente:
import wx
class Mywin(wx.Frame):
def __init__(self, parent, title):
super(Mywin, self).__init__(parent, title = title,size = (500,300))
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Centre()
self.Show(True)
def OnPaint(self, e):
dc = wx.PaintDC(self)
brush = wx.Brush("white")
dc.SetBackground(brush)
dc.Clear()
dc.DrawBitmap(wx.Bitmap("python.jpg"),10,10,True)
color = wx.Colour(255,0,0)
b = wx.Brush(color)
dc.SetBrush(b)
dc.DrawCircle(300,125,50)
dc.SetBrush(wx.Brush(wx.Colour(255,255,255)))
dc.DrawCircle(300,125,30)
font = wx.Font(18, wx.ROMAN, wx.ITALIC, wx.NORMAL)
dc.SetFont(font)
dc.DrawText("Hello wxPython",200,10)
pen = wx.Pen(wx.Colour(0,0,255))
dc.SetPen(pen)
dc.DrawLine(200,50,350,50)
dc.SetBrush(wx.Brush(wx.Colour(0,255,0), wx.CROSS_HATCH))
dc.DrawRectangle(380, 15, 90, 60)
ex = wx.App()
Mywin(None,'Drawing demo')
ex.MainLoop()
El código anterior produce la siguiente salida:
Provisión de drag and dropes muy intuitivo para el usuario. Se encuentra en muchas aplicaciones de escritorio donde el usuario puede copiar o mover objetos de una ventana a otra con solo arrastrarlo con el mouse y soltarlo en otra ventana.
La operación de arrastrar y soltar implica los siguientes pasos:
- Declarar un objetivo de caída
- Crear objeto de datos
- Crear wx.DropSource
- Ejecutar operación de arrastre
- Cancelar o aceptar drop
En wxPython, hay dos destinos de colocación predefinidos:
- wx.TextDropTarget
- wx.FileDropTarget
Muchos widgets de wxPython admiten la actividad de arrastrar y soltar. El control de origen debe tener habilitado el arrastre, mientras que el control de destino debe estar en posición de aceptar (o rechazar) el arrastre.
Los datos de origen que el usuario arrastra se colocan en el objeto de destino. OnDropText () del objeto de destino consume los datos. Si lo desea, se pueden eliminar los datos del objeto de origen.
Ejemplo
En el siguiente ejemplo, dos objetos ListCrl se colocan horizontalmente en un Box Sizer. La lista de la izquierda se completa con datos de idiomas []. Está designado como fuente de arrastre. Uno a la derecha es el objetivo.
languages = ['C', 'C++', 'Java', 'Python', 'Perl', 'JavaScript', 'PHP', 'VB.NET','C#']
self.lst1 = wx.ListCtrl(panel, -1, style = wx.LC_LIST)
self.lst2 = wx.ListCtrl(panel, -1, style = wx.LC_LIST)
for lang in languages:
self.lst1.InsertStringItem(0,lang)
El segundo control de lista está vacío y es un argumento para el objeto de la clase TextDropTarget.
class MyTextDropTarget(wx.TextDropTarget):
def __init__(self, object):
wx.TextDropTarget.__init__(self)
self.object = object
def OnDropText(self, x, y, data):
self.object.InsertStringItem(0, data)
El método OnDropText () agrega datos de origen en el control de la lista de destino.
La operación de arrastre es inicializada por el archivador de eventos.
wx.EVT_LIST_BEGIN_DRAG(self, self.lst1.GetId(), self.OnDragInit)
La función OnDragInit () coloca los datos de arrastre en el destino y los elimina del origen.
def OnDragInit(self, event):
text = self.lst1.GetItemText(event.GetIndex())
tobj = wx.PyTextDataObject(text)
src = wx.DropSource(self.lst1)
src.SetData(tobj)
src.DoDragDrop(True)
self.lst1.DeleteItem(event.GetIndex())
El código completo es el siguiente:
import wx
class MyTarget(wx.TextDropTarget):
def __init__(self, object):
wx.TextDropTarget.__init__(self)
self.object = object
def OnDropText(self, x, y, data):
self.object.InsertStringItem(0, data)
class Mywin(wx.Frame):
def __init__(self, parent, title):
super(Mywin, self).__init__(parent, title = title,size = (-1,300))
panel = wx.Panel(self)
box = wx.BoxSizer(wx.HORIZONTAL)
languages = ['C', 'C++', 'Java', 'Python', 'Perl', 'JavaScript',
'PHP', 'VB.NET','C#']
self.lst1 = wx.ListCtrl(panel, -1, style = wx.LC_LIST)
self.lst2 = wx.ListCtrl(panel, -1, style = wx.LC_LIST)
for lang in languages:
self.lst1.InsertStringItem(0,lang)
dt = MyTarget(self.lst2)
self.lst2.SetDropTarget(dt)
wx.EVT_LIST_BEGIN_DRAG(self, self.lst1.GetId(), self.OnDragInit)
box.Add(self.lst1,0,wx.EXPAND)
box.Add(self.lst2, 1, wx.EXPAND)
panel.SetSizer(box)
panel.Fit()
self.Centre()
self.Show(True)
def OnDragInit(self, event):
text = self.lst1.GetItemText(event.GetIndex())
tobj = wx.PyTextDataObject(text)
src = wx.DropSource(self.lst1)
src.SetData(tobj)
src.DoDragDrop(True)
self.lst1.DeleteItem(event.GetIndex())
ex = wx.App()
Mywin(None,'Drag&Drop Demo')
ex.MainLoop()
El código anterior produce la siguiente salida: