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: