15
Organización de widgets en wxPython (Parte II) Publicado por Pablo Tilli a las03:14 . Etiquetas:Python Si has llegado aquí mediante un buscador o por simple casualidad, te cuento que estas en la segunda parte de un tutorial que empieza AQUI . Trabajando con los Sizers Todos los sizers tienen algunas características en común; y otras, que hacen que cada uno de ellos sea único. Podríamos ver una a una cuales son las similitudes y cuales las diferencias para luego pasar a la practica con cosas concretas, pero no quiero que tengas que leer un montón de teoría antes de poder ver algo de practica, es por esto que iré intercalando la teoría y la practica de manera que el tutorial no se te haga muy tedioso. Creo que va a ser mas fácil partir de un sizer en particular (el GridSizer en este caso), y luego ir explicando en que se parecen y en que se diferencian a medida que vayamos avanzando con cada uno de los otros sizers. Hay distintos enfoques a la hora de trabajar con interfaces gráficas con Wxpython: 1- Escribir todo el código necesario para ir generando la interface gráfica; llamando a las funciones de wxPython que permiten crear los distintos widgets (botones, listas, etc.) desde la propia aplicación que estemos desarrollando. 2- Generar un archivo XML que describe la interface gráfica, y que luego podemos cargar desde la aplicación. 3- Utilizar un IDE para diseñar la interface gráfica. En este método, trabajamos de la misma manera que en método 2, excepto que es el propio IDE el que genera el archivo XML para que después lo carguemos desde nuestra aplicación.

Organización de widgets en wxPython

Embed Size (px)

Citation preview

Organización de widgets en wxPython (Parte II)

Publicado por Pablo Tilli a las03:14 .

Etiquetas:Python

Si has llegado aquí mediante un buscador o por simple casualidad, te cuento que

estas en la segunda parte de un tutorial que empieza AQUI.

Trabajando con los Sizers

Todos los sizers tienen algunas características en común; y otras, que hacen que

cada uno de ellos sea único. Podríamos ver una a una cuales son las similitudes y

cuales las diferencias para luego pasar a la practica con cosas concretas, pero no

quiero que tengas que leer un montón de teoría antes de poder ver algo de

practica, es por esto que iré intercalando la teoría y la practica de manera que el

tutorial no se te haga muy tedioso. Creo que va a ser mas fácil partir de un sizer en

particular (el GridSizer en este caso), y luego ir explicando en que se parecen y en

que se diferencian a medida que vayamos avanzando con cada uno de los otros

sizers.

Hay distintos enfoques a la hora de trabajar con interfaces gráficas con Wxpython:

1- Escribir todo el código necesario para ir generando la interface gráfica; llamando

a las funciones de wxPython que permiten crear los distintos widgets (botones,

listas, etc.) desde la propia aplicación que estemos desarrollando.

2- Generar un archivo XML que describe la interface gráfica, y que luego podemos

cargar desde la aplicación.

3- Utilizar un IDE para diseñar la interface gráfica. En este método, trabajamos de la

misma manera que en método 2, excepto que es el propio IDE el que genera el

archivo XML para que después lo carguemos desde nuestra aplicación.

De los tres métodos, vamos a empezar por el tercero. El IDE que vamos a usar

seráwxFormBuilder, pero existen otros como XRCed y wxGlade por nombrar sólo

algunos mas. Este método es el mas práctico porque (al igual que en el segundo)

logramos independizar la parte gráfica de la aplicación, del resto del código de la

aplicación en sí. A diferencia del segundo método, es mucho mas fácil delegar la

tarea de escribir el archivo XML en el IDE. Mas adelante veremos el primero y

segundo metodo tambien.

En mi caso trabajo sobre Ubuntu Intrepid Ibex (8.10), pero wxFormBuilder es un IDE

multiplataforma. Por lo menos en el caso de la mayoría de las distribuciones

populares de Linux, ya viene en los repositorios. Los usuarios de Windows y Mac los

pueden descargar desde el sitio del proyecto. wxFormBuilder es libre y gratuito.

A continuación te muestro una captura de pantalla para que te vayas familiarizando

con el programa:

Una vez que tenemos wxFormBuilder instalado en nuestro sistema, ya estamos

listos para empezar a trabajar.

Antes de poder crear un Sizer, debemos generar algún tipo de formulario que lo

contenga. Para este ejemplo crearemos un Frame como contenedor, el cual

visualmente no es mas que una clásica ventana (con su borde, botones de cerrar,

minimizar y maximizar, etc). Para esto vamos a la solapa “Forms” de la paleta de

componentes de wxFormBuilder y pulsamos el botón "Frame". Veamos una imágen

para que se entienda mejor:

Luego de pulsar el

botón “Frame”, el resultado será el siguiente:

Ahora que tenemos

creado el Frame, ya podemos agregar nuestro Sizer, que como dije antes, será un

GridSizer. Para logra esto, lo hacemos del mismo modo que agregamos el Frame,

sólo que ahora vamos a la solapa “Layout” y pulsamos el botón “wxGridSizer”:

El resultado lo vemos en la siguiente captura:

En la imágen se

muestran resalatadas 3 cosas importantes:

1- El panel izquierdo de wxFormBuilder ("Object Tree"), nos muestra toda la

interface en forma de árbol. En la imagen podemos apreciar que la raíz es el

proyecto en si (Proyect1 en este caso), inmediatamente después se encuentra el

Frame (llamado MyFrame2), y por último, dentro del Frame esta el GridSizer que

acabamos de agregar (cuyo nombre es gSizer1).

2- Si miramos bien dentro del Frame que creamos, veremos que el GridSizer esta

representado por un rectángulo rojo que ocupa todo el interior del Frame.

3- El panel derecho de wxFormBuilder ("Object Properties"), nos muestra las

propiedades del objeto que esta seleccionado actualmente en el Editor.

Para ver como se comporta el GridSizer, iremos agregando algunos widgets dentro

de éste. A modo de ejemplo, agregaremos cuatro botones. Esto realmente no tiene

ninguna complejidad, ya que el modo de trabajo es el mismo que usamos hasta

aquí. Ante todo, verificamos que esté seleccionado "gSizer1" en el "Object Tree" de

wxFormBuilder; de modo que el IDE "sepa" que los botones irán dentro del

GridSizer, luego vamos a la solapa“Common” y pulsamos el botón “wxButton”.

Esto agregará el primer botón al GridSizer.

Tras pulsar el botón “wxButton”, el Editor quedará como se ve a continuación:

Como podemos apreciar

el botón se creo en la esquina superior izquierda del GridSizer, ahora crearemos el

segundo botón. Para esto sólo pulsamos nuevamente el botón“wxButton”, con lo

cual el Editor ahora quedara así:

El segundo botón fue creado a la derecha del otro (pero con bastante espacio de

por medio). Sólo nos falta crear los dos botones restantes. Si has llegado hasta acá,

seguramente te imaginaras como hacerlo … claro, pulsas dos veces mas el

botón“wxbutton” (recuerda que debe estar seleccionado "gSizer1" en el "Object

Tree"). El resultado final que debes ver en el Editor es el siguiente:

Como te habrás dado cuenta, los últimos dos botones se encuentran en una

segunda fila (pero siempre alineados verticalmente con la primera). Tal vez todavía

no te hayas dado cuenta (o tal vez si), pero la distribución que conseguimos tiene

una lógica. Con la siguiente imagen tal vez lo veas mas claro:

Como muestra la imágen, y como el nombre del Sizer lo indica, un GridSizer no es

mas que una grilla, donde en cada celda podemos ir agregando el widget que

necesitemos. Hasta aquí hemos visto como agregar un Frame, un GridSizer y cuatro

botones dentro de éste.

Es importante que le vayas prestando atención al "Object Tree" de wxFormBuilder.

Este "árbol" nos da una clara visión de como se relacionan los distintos elementos

de nuestra interface. Entender este “árbol” también te servirá mucho si en algún

momento decides trabajar con el IDE XRCed (en otro tutorial lo veremos).

Veamos un poco mas en detalle el GridSizer.

Grid Sizer (wx.Grid Sizer)

Como ya hemos dicho, el GridSizer consiste en una grilla bidimensional, en la cual

se organizan los distintos widgets que necesitemos. Gráficamente un GridSizer no

es mas que una grilla, donde en cada celda podemos posicionar un widget.

El primer widget que se agrega a un GridSizer se ubica en la esquina superior

izquierda de la grilla; el resto se ubican de izquierda a derecha, y al llegar a la

ultima columna de una fila, se continua en la primera columna de la fila

inmediatamente inferior hasta llegar a la ultima celda de la grilla, que corresponde

a la esquina inferior derecha de la misma. Este comportamiento, lo habrás visto

bien claro si fuiste haciendo el ejemplo de agregar cuatro botones dentro del

GridSizer con wxFormBuilder; cada vez que pulsas el botón que agrega un

wxButton, puedes observar donde se posiciona el botón dentro de la grilla. Si no

hiciste el ejemplo, te invito a que lo hagas!.

Al redimensionar un GridSizer, cada celda de este, agranda o disminuye su tamaño

proporcionalmente, pero por defecto, los widgets contenidos en cada una de las

celdas, mantienen su tamaño original, y quedan “anclados” a la esquina superior

izquierda de la celda en la que se encuentran. Veamos una captura, donde vemos 2

veces una misma ventana, pero antes y después de ser redimensionada. La

ventana contiene un GridSizer que tiene cuatro botones en su interior (el ejemplo

que hicimos antes).

En la imagen, se puede

apreciar como las cuatro celdas, crecen de manera idéntica, siendo en todo

momento todas las celdas del mismo alto y ancho, pero como vemos los widgets no

cambiaron su tamaño. Si bien todas las celdas tienen el mismo tamaño, no

necesariamente el alto de las filas es igual al ancho de las columnas.

Como hemos visto; al crear un GridSizer con wxFormBuilder, nuestra grilla es de 2 X

2 en forma predeterminada, pero obviamente tenemos una forma de cambiar esto.

Entre las propiedades particulares del GridSizer se encuentran Rows y Cols, las

cuales nos permiten establecer la cantidad de filas y columnas respectivamente. Si

lo deseamos, también podemos especificar que haya un espacio entre las distintas

celdas; para esto contamos con la propiedad hgap para crear un espacio entre las

filas, y vgap para lograr el espaciado entre las columnas. El valor de vgap y hgap,

es un numero entero que representa el espaciado en pixeles. En la imagen

siguiente, vemos una una grilla de 3 X 2, con un espacio horizontal entre las celdas

de 2px y un espaciado vertical entre celdas de 3px:

Para lograrlo, simplemente seleccionamos el GridSizer ("gSizer1") desde el “Object

Tree” y luego establecemos los valores en el panel de propiedades (rows=2,

cols=3, vgap=3 y hgap=2).

Si bien dijimos que todas las celdas tienen el mismo tamaño, esto no quiere decir

que todos los elementos que estén en cada una de ellas, también deban tener las

mismas dimensiones ni tampoco la misma posición dentro la celda.

Como dijimos antes, al agregar un elemento en un GridSizer, por defecto éste

queda posicionado en la esquina superior izquierda de la celda que le corresponda,

y su tamaño NO se ve afectado al cambiar el tamaño del sizer. Este

comportamiento puede ser modificado a través de los Flags. Los Flags entran

dentro de las características comunes a todos los widgets que se encuentren

contenidos en un Sizer. Para entender mejor de que hablamos, veremos cuales son

los Flags y para que sirve cada uno de ellos.

Flags para establecer la alineación de los widgets

Las opciones disponibles para alinear los widgets que agregamos a los Sizers son

las siguientes:

wx.ALIGN_TOP: El widget es alineado en la parte superior de la celda en la que se

encuentre, si se omite, esta es la opcion por defecto.

wx.ALIGN_BOTTOM: El widget se alinea en la parte inferior de la celda en la que

es insertado.

wx.ALIGN_LEFT: El widget es alineado a la izquierda dentro la celda en la que se

encuentre, si se omite, esta es la opcion por defecto.

wx.ALIGN_RIGHT: El widget es alineado a la derecha dentro la celda en la que se

encuentre.

wx.ALIGN_CENTER_HORIZONTAL: El widget es centrado en forma horizontal. Se

omite el valor de wx.ALIGN_LEFT y wx.ALIGN_RIGHT.

wx.ALIGN_CENTER_VERTICAL: El widget es centrado en forma vertical. Se omite

el valor de wx.ALIGN_TOP y wx.ALIGN_BOTTOM.

wx.ALIGN_CENTER: El widget se alinea en la centro de la celda en la que es

insertado. En este caso se omiten todas las opciones anteriores.

wx.EXPAND: El widget toma el mismo tamaño que la celda en la que se encuentra.

wx.FIXED_MINSIZE: El widget mantiene siempre su tamaño mínimo (Luego

volveremos sobre este punto).

wx.SHAPED: El widget cambiara su tamaño de forma proporcional, manteniendo

su relación de aspecto (luego lo veremos con un ejemplo, para que se entienda

mejor).

wx.GROW: Funciona igual que wx.EXPAND.

Flags para establecer un borde (espacio) entre los widgets

Además de poder cambiar la alineación de los widgets, tenemos la

posibilidad de dejar un borde (espacio) entre el widget y la celda que lo

contiene. Para establecer este valor, podemos combinar las siguientes

opciones junto con las de alineación que vimos anteriormente:

wx.TOP: Establece que el espacio especificado en la propiedad “border”,

sea aplicado en la parte superior del widget.

wx.LEFT: Establece que el espacio especificado en la propiedad “border”,

sea aplicado a la izquierda del widget.

wx.RIGHT: Establece que el espacio especificado en la propiedad “border”,

sea aplicado a la derecha del widget.

wx.BOTTOM: Establece que el espacio especificado en la propiedad

“border”, sea aplicado en la parte inferior del widget.

wx.ALL: El espacio se establece a todos los lados del widget (Arriba,

Izquierda, Derecha y Abajo). Es la suma de las cuatro opciones anteriores

juntas.

Luego veremos algunas imágenes donde se puedan apreciar los resultados

de combinar estos valores de distintas formas.

Para que esta segunda parte no se haga mas larga, vamos a dejar aquí. En

esta parte, hemos avanzado bastante, y cada vez estamos mas cerca de

poder crear una interface mas “real” (léase útil).

Repasando un poco, hasta aquí dijimos que existen tres métodos para

trabajar con interfaces gráficas con wxPython, y que por ahora usaremos

la alternativa del IDE. Estuvimos viendo como se trabaja con

wxFormBuilder, hablamos de los Flags, y tenemos una idea mas clara de

como funciona el GridSizer.

Para dominar de forma fluida el diseño de interfaces gráficas con

wxPython, se requiere mucha práctica. Al principio puede ser un poco

desalentador, ya que cuesta mucho lograr lo que uno tiene en mente; y

sobre todo si eres un desarrollador que viene de otros lenguajes (como

Visual Basic, por ejemplo) donde la forma de trabajo es bastante distinta,

pero con el tiempo te darás cuenta de las ventajas que tiene esta manera

de hacer las cosas, y podras ir logrando lo que te propones.

Cualquier duda o sugerencia, puedes comentar.

... continuando con los Flags

En la segunda parte de este tutorial, les había prometido continuar con el tema de los Flags, y esto es lo que trataremos justamente ahora.

El primer caso que veremos, será sobre el Flag de alineación wx.ALIGN_CENTER:

En la imagen podemos apreciar el Editor (Arriba) y el panel de propiedades (Abajo) de wxFormBuilder. En el Editor dibuje una grilla de color rojo, para que tengas de

referencia el tamaño de cada celda. Como ya habíamos dicho, en un GridSizer todas las celdas son iguales, y de echo esto lo puedes apreciar en la imagen, pero como puedes ver, en la primera celda (Fila 0, Col. 0) el widget se encuentra con una alineación distinta a la del resto. Para lograr esto, en el Editor debes seleccionar el widget con el que quieres trabajar, y luego en el panel de propiedades desplegar la sección Flags (lo puedes ver en la parte de abajo de la imagen), y activar la opción wxALIGN_CENTER.

En la captura de pantalla, se pueden ver desplegados todos los Flags. Si quisiéramos cambiar alguno de ellos, simplemente la activamos o desactivamos desde el checkbox que tienen a la derecha.

En el siguiente ejemplo vamos a combinar algunos de ellos:

En este ejemplo vemos que cada una de los widgets posee una alineación distinta. Las opciones aplicadas en cada caso son las siguientes:

1- wx.ALIGN_CENTER

2- wx.ALIGN_BOTTOM + wx.ALIGN_RIGHT

3- wx.ALIGN_CENTER_VERTICAL

4- wx.ALIGN_CENTER_HORIZONTAL + wx.ALIGN_CENTER_BOTTOM

5- wx.ALIGN_CENTER_VERTICAL + wx.ALIGN_RIGHT

6- wx.ALIGN_BOTTOM

Si miras con detenimiento en la imagen, te puedes dar cuenta que los widgets nunca llegan hasta el borde de las “celdas virtuales” (que por claridad, yo las dibuje en rojo). Esto se debe a que el valor de la propiedad “border” esta en 5, y esta aplicado a los cuatro lados de los widgets (wx.ALL). En el ejemplo siguiente, variaremos los bordes (además de la alineación):

Las opciones de cada widget de la imagen son los siguientes:

1- border=0 + wx.ALIGN_RIGHT + wx.ALL

2- border=30 + wx.ALIGN_RIGHT + wx.RIGHT

3- border=40 + wx.LEFT + wx.TOP

4- border=30 + wx.ALIGN_LEFT

Ahora veremos un ejemplo donde usaremos los Flags wx.EXPAND, wx.SHAPED ywx.GROW.

Los Flags utilizados en cada widget de la imagen, son los siguientes:

1- border=0 + wx.ALL + wx.EXPAND

2- border=5 + wx.ALL + wx.SHAPED

3- border=20 + wx.ALL + wx.EXPAND

4- No hay widget en esta celda.

Si bien en las celdas 1 y 3 estamos usando el Flag wx.EXPAND, y por lo tanto los widgets deben ocupar la totalidad del espacio de la celda en la que estén, pareciera que en la celda 3 no se cumple, pero en realidad si. La diferencia entre las dos celdas, es que la primera tiene un borde de 0px en todos sus lados, y la celda 3

tiene un borde de 20px en todos sus lados, por lo que puedes deducir que con el Flag wx.EXPAND, el widget se expande, pero contempla los bordes especificados en la propiedad “border”.En el caso de la celda 2, es difícil entender como funciona el Flag wx.SHAPED, así que te voy a mostrar dos imágenes donde se encuentra la misma ventana, pero en dos tamaños distintos:

En estas ultimas 2 capturas, vemos que la celda 2, al utilizar el Flag wx.SHAPED,

hace que al agrandarse o achicarse la ventana, el widget lo haga también en forma

proporcional. Para que lo veas aun mejor, aislé el botón de la celda 2, de las dos

imágenes y aquí los tienes uno debajo del otro:

En este punto seria bueno que experimentes tu mismo combinando los distintos

Flags que hemos visto. El Flag wx.GROW no se encuentra disponible en

wxFormsBuilder, y esto es así porque en realidad (como dijimos antes) es lo mismo

que wx.EXPAND.

Por ahora llegaremos hasta aquí. A partir de la próxima parte del tutorial,

seguiremos viendo el resto de los Sizers. Si bien esta parte no fue muy extensa, era

necesaria para que podamos continuar.

Recuerda que puedes dejar tus dudas, sugerencias, experiencias o lo que quieras

para que todos podamos aprender de ti también.