11. Interfaces visuales¶
11.1. Abeille¶
El programa Abeille lo usaremos para la creación de las interfaces visuales. En este programa podremos establecer el aspecto de las ventanas, nombres, etc. Haciendo uso de la librería FormPanel podremos cargarlo fácilmente en un script, y sacarle el máximo partido.
Abriremos el Abeille desde el botón situado en la barra de Herramientas del Scripting Composer.
Nota
Recordar que para que aparezca la herramienta de Abeille, debemos de tener instaladas las herramientas denominadas ScriptingComposerTools que podrás descargar desde el Administrador de Complementos.
Aparece en la imagen el programa Abeille con el ejemplo de coordenadas.xml abierto:
![../../../_images/abeille.png](../../../_images/abeille.png)
11.2. Ejemplo de uso¶
Descargar el ejemplo explicado a continuación: CentrarCoordenadas
![../../../_images/abeille_1.png](../../../_images/abeille_1.png)
Para crear una interfaz visual crearemos un nuevo formulario en Abeille.
![../../../_images/abeille_2.png](../../../_images/abeille_2.png)
Crearemos una nueva etiqueta label
.
![../../../_images/abeille_3.png](../../../_images/abeille_3.png)
Presionamos el lugar en el que queremos situarlo en la cuadrícula.
![../../../_images/abeille_4.png](../../../_images/abeille_4.png)
Ahora podemos dotarle de nombre a la etiqueta. Este nombre es con el que accederemos al componente desde nuestro script. En este caso, le daremos de nombre lblName
.
![../../../_images/abeille_5.png](../../../_images/abeille_5.png)
Cambiamos el texto que contendrá esta etiqueta a: Coordenadas
![../../../_images/abeille_6.png](../../../_images/abeille_6.png)
Se puede ampliar el rango de ocupación de esta casilla en el formulario para ajustarlo mejor al interfaz que vamos a crear. En este caso queremos que ocupe 3 columnas de nuestro grid, dejando una columna por cada lado para que los componentes que estamos creando no estén juntos al borde de la ventana.
![../../../_images/abeille_7.png](../../../_images/abeille_7.png)
Vemos que el espacio que ocupa la etiqueta de Coordenas se ha ampliado. Para la interfaz de este script haremos uso de 5 columnas, 3 para situar los componentes y las otras dos de separación con los bordes. Ya podemos eliminar las columnas que no tenemos planeado utilizar. Para ello hacemos uso del control “Delete Columns”:
![../../../_images/abeille_71.png](../../../_images/abeille_71.png)
Vamos a ampliar la anchura de algunas columnas del formulario para una mejor visualización, aunque al final explicaremos otras opciones para que el panel se encargue automáticamente de este ancho y nos aseguremos de una correcta visualización. Para ello, solo tenemos que presionar sobre la columna a modificar y desplazar la señal que aparecerá arriba hacia la derecha:
![../../../_images/abeille_72.png](../../../_images/abeille_72.png)
Repetimos el proceso para crear dos etiquetas más denominadas lblX
y lblY
, con textos de “X: ” e “Y: ” respectivamente. Dejaremos una fila entre cada uno de ellos para una correcta visualización:
![../../../_images/abeille_8.png](../../../_images/abeille_8.png)
Ahora crearemos un text field
o campo de texto. Este campo permitirá tanto mostrar valores, como permitir al usuario introducirlos:
![../../../_images/abeille_9.png](../../../_images/abeille_9.png)
Repetimos el mismo proceso anterior para la creación de dos text fields denominados txtX
y txtY
.
![../../../_images/abeille_10.png](../../../_images/abeille_10.png)
A esta columna en la que se sitúan las cajas de texto, vamos a dotarla de la posibilidad de agrandarse en caso necesario, por ejemplo, si el usuario agranda la ventana. Esta opción ayudará a mantener a la correcta visualización de la interfaz, y nos da la opción de detallar los componentes que permitimos que cambien de tamaño.
Para ello, vamos a seleccionar alguna celda situada en la columna que contiene los componentes de Cajas de Texto, y vamos a ir al menú de arriba
.![../../../_images/abeille_101.png](../../../_images/abeille_101.png)
Vemos como ya la previsualización del formulario ha cambiado, apareciendo más grande haciendo uso de esta columna designada:
![../../../_images/abeille_102.png](../../../_images/abeille_102.png)
El siguiente paso es crear espacio para los botones de la aplicación, que en este caso, serán dos. El primer botón destinado a realizar una acción que será la de Centrar: btnCenter
, y otro botón destinado a cerrar la aplicación: btnClose
.
Para tener mayor libertad de configuración en la posición y tamaño de estos botones, así como de ayudar a una correcta visualización de la interfaz, vamos a hacerlo de la siguiente manera.
Primero vamos a insertar un componente de tipo “Embedded Form”. Esta opción nos permite insertar un formulario dentro de otro.
![../../../_images/abeille_103.png](../../../_images/abeille_103.png)
Situaremos el nuevo componente debajo de la última etiqueta, dejando una fila de separación:
![../../../_images/abeille_104.png](../../../_images/abeille_104.png)
Nos aparecerá una ventana para indicar qué tamaño de formulario queremos insertar, le indicaremos 4 columnas y 1 fila. De esta forma tendremos espacio para situar los dos botones y dejar separación entre ellos.
![../../../_images/abeille_105.png](../../../_images/abeille_105.png)
Dando como resultado algo similar a:
![../../../_images/abeille_106.png](../../../_images/abeille_106.png)
Una vez insertado, le indicaremos que ocupe también las siguientes dos columnas, de la misma forma que hicimos con la primera etiqueta Coordenadas, usando Increse Column Span
.
![../../../_images/abeille_107.png](../../../_images/abeille_107.png)
Dejando una fila de separación para el borde de abajo, podemos eliminar también el resto de filas sobrantes. El resultado será similar al siguiente:
![../../../_images/abeille_108.png](../../../_images/abeille_108.png)
Vamos a indicarle que este subformulario se alinea a la derecha de la celda en la que está contenido. Presionamos sobre la celda que contiene el subformulario y a la derecha en
, quedando como resultado:![../../../_images/abeille_109.png](../../../_images/abeille_109.png)
Ahora ya podemos crear los botones en este subformulario, btnCenter
y btnClose
. Seleccionamos la opción jButton:
![../../../_images/abeille_110.png](../../../_images/abeille_110.png)
Y situamos los dos botones dentro del subformulario:
![../../../_images/abeille_111.png](../../../_images/abeille_111.png)
Está la opción de ampliar este subformulario por si nos enfrentamos a un caso más complicado:
![../../../_images/abeille_112.png](../../../_images/abeille_112.png)
Aparecerá el formulario en una pestaña diferente:
![../../../_images/abeille_113.png](../../../_images/abeille_113.png)
Con esto ya tendremos la interfaz preparada, solo tendremos que guardarla en el mismo directorio del script que estábamos creando con extensión .xml
:
![../../../_images/abeille_114.png](../../../_images/abeille_114.png)
En cualquier momento podremos realizar cambios en este interfaz abriendo el fichero .xml
de nuevo desde el Abeille.
Aquí vemos como responde la aplicación a diferentes tamaños que le vamos dando:
![../../../_images/abeille_115.png](../../../_images/abeille_115.png)
Desde código podemos establecer el tamaño que queremos que tenga la ventana con la línea self.setPreferredSize(300,300)
, quedando algo similar según el script que tengamos a:
from gvsig import *
from gvsig.libs.formpanel import FormPanel
class Panel(FormPanel):
def __init__(self):
FormPanel.__init__(self, os.path.join(os.path.dirname(__file__), "ui_basic.xml"))
self.setPreferredSize(300,300)
def main(*args):
l = Panel()
l.showTool("Visual")
pass
También tenemos muchas más opciones que nos permiten configurar con más detalle la forma de reaccionar de nuestros componentes en la interfaz, como por ejemplo, en el menú de opciones de Columna:
![../../../_images/abeille_116.png](../../../_images/abeille_116.png)
11.3. Uso de FormPanel¶
Para la creación de script visuales nos apoyaremos en la clase FormPanel contenida en gvsig.libs.formpanel
. Crearemos una clase nueva que contendrá la funcionalidad de nuestro script y extenderemos desde FormPanel.
Primero vamos a crear una carpeta nueva en la que meter nuestro ejemplo.
![../../../_images/abeille_script_1.png](../../../_images/abeille_script_1.png)
Después, un script en esta carpeta denominado centrar_coordenadas.py.
![../../../_images/abeille_script_2.png](../../../_images/abeille_script_2.png)
Guardaremos el formulario explicado en el apartado anterior en esta carpeta.
Ejemplo básico de la carga de una interfaz en un script:
from gvsig import *
from gvsig.libs.formpanel import FormPanel
import os
class Panel(FormPanel):
def __init__(self):
FormPanel.__init__(self, os.path.join(os.path.dirname(__file__), "ui_basic.xml"))
def main(*args):
l = Panel()
l.showTool("Visual")
pass
Nos vamos a basar en esta plantilla para la creación de nuestro script de centrar_coordenadas.py.
Por defecto, en FormPanel viene establecido un método btnClose_click
, que servirá para cerrar este script. De esta forma solo tenemos que establecer en Abeille un botón denominado btnClose
y ya tendremos un botón programado para el cierre de la aplicación.
Tenemos nuestro módulo listo para ser programado. Tenemos una carpeta que contiene el script y la interfaz que utilizará.
![../../../_images/abeille_script_3.png](../../../_images/abeille_script_3.png)
Seguimos desarrollando las funcionalidades de FormPanel. Una de ellas es el auto enlace con eventos que se producen en los elementos de la interfaz visual. Por ejemplo, si tenemos (en nuestro ejemplo) un botón denominado btnCenter
y queremos que reaccione al evento cuando lo presionemos, tan solo deberemos de crear un método en nuestra clase que contenga el nombre del elemento “btnCenter” terminado con el evento que queremos capturar “_click”.
De esta forma no tenemos que preocuparnos de eventos, ya que la propia librería FormPanel nos lo gestionará:
# encoding: utf-8
from gvsig import *
from gvsig.libs.formpanel import FormPanel
import os
class CenterCoordinates(FormPanel):
def __init__(self):
FormPanel.__init__(self,
os.path.join(os.path.dirname(__file__),
"centrar_coordenadas.xml")
)
def btnCenter_click(self, *args):
print "Clicked!"
def btnClose_click(self,*args):
self.hide()
def main(*args):
l = CenterCoordinates()
l.showTool("Centrar Coordenadas")
pass
Al ejecutar el script nos aparecerá una interfaz similar a esta:
![../../../_images/abeille_script_4.png](../../../_images/abeille_script_4.png)
Y lo que ocurre al presionar el botón Centrar, tal y como hemos programado en el método btnCenter_click, mostrará por consola la palabra Clicked!.
![../../../_images/abeille_script_5.png](../../../_images/abeille_script_5.png)
Si presionamos el botón de Cerrar se cerrará la aplicación, haciendo uso de un método ya implementado en la clase FormPanel, sin necesidad de programarlo nosotros mismos. En el caso de que quisiéramos encargarnos nosotros de esta función, solo tendríamos que sobrescribir el método en nuestra clase, o darle otro nombre al componente de cerrar la aplicación.
Por ejemplo, también podríamos modificar el texto de etiquetas u otros valores de una forma similar a:
self.txtX.setText("Clicked!")
self.txtY.setText("Clicked!")
![../../../_images/abeille_script_7.png](../../../_images/abeille_script_7.png)
Como hemos visto, para acceder a nuestros componentes en el interfaz, lo haremos mediante self. + nombre del componente. Por ejemplo, vamos a implementar en el botón Centrar, que muestre por consola las coordenadas que el usuario escriba en las cajas de texto.
Para ello haremos referencia a los componentes de cajas de texto txtX
y txtY
que hemos programado en la interfaz:
def btnCenter_click(self, *args):
x = self.txtX.getText()
y = self.txtY.getText()
print "X: ", x, " Y: ", y
Aquí vemos como quedaría:
![../../../_images/abeille_script_6.png](../../../_images/abeille_script_6.png)
Ahora, para cumplir el propósito del script, centrar la vista en unas coordenadas que le establezcamos, solo tenemos que modificar el método btnCenter_click por algo similar a lo siguiente:
# encoding: utf-8
from gvsig import *
from gvsig import geom
from gvsig.libs.formpanel import FormPanel
import os
class CenterCoordinates(FormPanel):
def __init__(self):
FormPanel.__init__(self,
os.path.join(os.path.dirname(__file__),
"centrar_coordenadas.xml")
)
def btnCenter_click(self, *args):
x = float(self.txtX.getText())
y = float(self.txtY.getText())
point = geom.createPoint2D(x, y)
currentView().centerView(point.getEnvelope())
def btnClose_click(self,*args):
self.hide()
def main(*args):
l = CenterCoordinates()
l.showTool("Centrar Coordenadas")
pass
Dando como resultado algo así:
![../../../_images/abeille_script_8.png](../../../_images/abeille_script_8.png)
Vemos como ha centrado la Vista en las coordenadas que hemos indicado en las cajas de texto.
11.4. Tratar con diferentes componentes¶
11.4.1. Grupos de RadioButton¶
Una función del interfaz habitual es la creación de un grupo de RadioButton para permitir la selección entre varias opciones. Por lo general, estas opciones van agrupadas y solo se permite la selección de una de ellas. Estas agrupaciones debemos de hacerlas por código de una forma similar a la siguiente.
Después de generar la interfaz en el método __init__
con FormPanel.__init__(..)
, tendremos que crear el grupo de botones y añadir uno a uno los que forman parte de la agrupación, por ejemplo:
from javax.swing import ButtonGroup
...
self.btgAnswers = ButtonGroup()
self.btgAnswers.add(self.rdbOption1)
self.btgAnswers.add(self.rdbOption2)
Siendo rdbOption1
y rdbOption2
, componentes de tipo RadioButton de la interfaz.
![../../../_images/interfaz_rdb.png](../../../_images/interfaz_rdb.png)
11.5. Eventos autoregistrados¶
Hemos comentado que FormPanel se encarga de enlazar los eventos de los componentes con nuestro script, pero no todos los eventos posibles de cada elemento del interfaz están implementados dentro de FormPanel (pero si necesitas alguno de ellos se podrían añadir o implementar en tu propia clase). Aquí mostramos algunos de estos eventos haciendo referencia a spinners, combobox, etc:
def btnCalcular_click(self, *args):
self.txtField.setText("Clicked!")
print "Clicked!"
def chb1_change(self, *args):
print "Check box!"
def rb1_change(self, *args):
print "Radio button!"
def cmb1_change(self, *args):
print "Combobox!"
def sld1_focusGained(self, *args):
print "Slider!", sld1.getValue()
def spn1_change(self, *args):
print "Spinner!"
def btnClose_click(self,*args):
self.hide()