QGIS 3.40 PyQGISDeveloperCookbook Es
QGIS 3.40 PyQGISDeveloperCookbook Es
40 developer cookbook
QGIS Project
28 de junio de 2025
Índice general
1 Introducción 3
1.1 Desarrollar scripts en la consola de Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Plugins Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2.1 Complementos de procesamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Ejecutar código Python cuando QGIS se inicia. . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3.1 El fichero [Link] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3.2 La variable de entorno PYQGIS_STARTUP . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3.3 El parámetro --code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3.4 Argumentos adicionales para Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4 Aplicaciones Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4.1 Usando PyQGIS en scripts individuales . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4.2 Usando PyQGIS en aplicaciones personalizadas . . . . . . . . . . . . . . . . . . . . . . 7
1.4.3 Ejecutar aplicaciones personalizadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.5 Notas técnicas sobre PyQt y SIP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2 Cargar proyectos 9
2.1 Resolver rutas erróneas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2 Uso de banderas para acelerar las cosas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3 Cargar capas 13
3.1 Capas Vectoriales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2 Capas ráster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.3 Instancia QgsProject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
i
6.3.2 Iterando sobre rasgos seleccionados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
6.3.3 Iterando sobre un subconjunto de rasgos . . . . . . . . . . . . . . . . . . . . . . . . . . 31
6.4 Modificación de capas vectoriales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
6.4.1 Añadir Entidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
6.4.2 Borrar Entidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
6.4.3 Modificar los objetos espaciales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
6.4.4 Modificación de capas vectoriales con un búfer de edición . . . . . . . . . . . . . . . . . 33
6.4.5 Agregando y Removiendo Campos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
6.5 Usar índice espacial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
6.6 La clase QgsVectorLayerUtils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
6.7 Creación de capas vectoriales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
6.7.1 Desde una instancia de QgsVectorFileWriter . . . . . . . . . . . . . . . . . . . . 37
6.7.2 Directamente desde las funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
6.7.3 Desde una instancia de QgsVectorLayer . . . . . . . . . . . . . . . . . . . . . . . . 39
6.8 Apariencia (Simbología) de capas vectoriales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
6.8.1 Representador de Símbolo Único . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
6.8.2 Representador de símbolo categorizado . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
6.8.3 Renderizador de símbolo graduado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
6.8.4 Trabajo con Símbolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
6.8.5 Crear Renderizados personalizados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
6.9 Más Temas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
7 Manejo de Geometría 51
7.1 Construcción de Geometría . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
7.2 Acceso a Geometría . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
7.3 Geometría predicados y Operaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
8 Soporte de Proyecciones 57
8.1 Sistemas de coordenadas de referencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
8.2 Transformación SRC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
ii
13.1 Mostrando mensajes. La clase QgsMessageBar . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
13.2 Mostrando el progreso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
13.3 Registro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
13.3.1 QgsMessageLog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
13.3.2 El python construído en el módulo de registro . . . . . . . . . . . . . . . . . . . . . . . . 90
14 Infraestructura de autenticación 91
14.1 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
14.2 Glosario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
14.3 QgsAuthManager el punto de entrada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
14.3.1 Inicie el administrador y configure la contraseña maestra . . . . . . . . . . . . . . . . . . 93
14.3.2 Complete authdb con una nueva entrada de configuración de autenticación . . . . . . . . . 93
14.3.3 Borrar una entrada de authdb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
14.3.4 Deje la expansión authcfg a QgsAuthManager . . . . . . . . . . . . . . . . . . . . . . . 95
14.4 Adpatar complementos para usar Infraestructura de Autenticación . . . . . . . . . . . . . . . . . . 96
14.5 Autenticación IGUs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
14.5.1 IGU para seleccionar credenciales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
14.5.2 IGU Editor Autenticación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
14.5.3 IGU de Editor de Autoridades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
iii
19 Biblioteca de análisis de redes 137
19.1 Información general . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
19.2 Contruir un gráfico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
19.3 Análisis gráfico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
19.3.1 Encontrar la ruta más corta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
19.3.2 Áreas de disponibilidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
iv
PyQGIS 3.40 developer cookbook
Índice general 1
PyQGIS 3.40 developer cookbook
2 Índice general
CAPÍTULO 1
Introducción
Este documento pretende ser tanto un tutorial y una guía de referencia. Aunque no enumera todos los casos de uso
posibles, debe proporcionar una buena visión general de la funcionalidad principal.
Se otorga permiso para copiar, distribuir y/o modificar este documento bajo los términos de la Licencia de
Documentación Libre GNU, Versión 1.3 o cualquier versión posterior publicada por la Free Software Foundation;
sin secciones invariantes, sin textos de portada y sin textos de contraportada.
Se incluye una copia de la licencia en la sección gnu_fdl.
Esta licencia también se aplica a todos los fragmentos de código de este documento.
El soporte de Python se introdujo por primera vez en QGIS 0.9. Hay varias maneras de utilizar Python en QGIS
Desktop (cubierto en las siguientes secciones):
• Emita comandos en la consola de Python dentro de QGIS
• Crear y usar plugins
• Ejecute automáticamente código Python cuando se inicie QGIS
• Crear algoritmos de procesamiento
• Crear funciones para expresiones en QGIS
• Crear aplicaciones personalizadas basadas en la API de QGIS
Los enlaces de Python también están disponibles para QGIS Server, incluidos los plugins de Python (vea Servidor
QGIS y Python) y los enlaces de Python que se pueden usar para incrustar QGIS Server en una aplicación de Python.
Hay una referencia API completa de QGIS C++ que documenta las clases de las librerías de QGIS. The Pythonic
QGIS API (pyqgis) es casi idéntica a la API de C++.
Otro buen recurso para aprender a realizar tareas comunes es descargar complementos existentes desde el repositorio
de complementos y examine su código.
3
PyQGIS 3.40 developer cookbook
QGIS provee una consola Python integrada para scripting. Se puede abrir desde el menu: Complementos ► Consola
de Python
La captura de pantalla anterior ilustra cómo obtener la capa seleccionada actualmente en la lista de capas, mostrar
su ID y opcionalmente, si se trata de una capa vectorial, mostrar el recuento de entidades. Para la interacción con el
entorno QGIS, hay una variable iface que es una instancia de la clase: QgisInterface <[Link]>. Esta
interfaz permite el acceso al lienzo del mapa, menús, barras de herramientas y otras partes de la aplicación QGIS.
Para mayor comodidad del usuario, las siguientes instrucciones se ejecutan cuando se inicia la consola (en el futuro
será posible establecer más comandos iniciales)
Para aquellos que utilizan la consola a menudo, puede ser útil establecer un acceso directo para activar la consola
(dentro de Configuración ► Atajos de teclado…)
La funcionalidad de QGIS se puede ampliar utilizando complementos. Los complementos se pueden escribir en
Python. La principal ventaja sobre los complementos de C++ es la simplicidad de la distribución (sin compilación
para cada plataforma) y el desarrollo más fácil.
Muchos complementos que cubren diversas funciones se han escrito desde la introducción del soporte de Python.
El instalador de complemento permite a los usuarios buscar, actualizar y eliminar fácilmente complementos
Python. Consulte la página Complementos de Python para más información sobre complementos y desarrollo de
complementos.
Crear plugins con Python es simple, vea Desarrollando Plugins Python para instrucciones detalladas.
Nota: Los plugins de Python están también disponibles para QGIS Server. Vea Servidor QGIS y Python para más
detalles.
4 Capítulo 1. Introducción
PyQGIS 3.40 developer cookbook
Los complementos de procesamiento se pueden utilizar para procesar datos. Son más fáciles de desarrollar, más
específicos y más livianos que los complementos de Python. Escribir nuevos complementos de procesamiento explica
cuándo es adecuado el uso de algoritmos de Processing y cómo desarrollarlos.
Existen diferentes métodos para ejecutar código Python cada vez que se inicia QGIS.
1. Crear un script [Link]
2. Configurar la variable de entorno PYQGIS_STARTUP a un fichero Python existente
3. Especificación de un script de inicio mediante el parámetro --code init_qgis.py.
Cada vez que se inicia QGIS, se busca en el directorio de Python del usuario y en una lista de rutas del sistema un
fichero llamado [Link]. Si ese archivo existe, es ejecutado por el intérprete de Python incrustado.
La ruta en el directorio personal del usuario suele encontrarse en:
• Linux: .local/share/QGIS/QGIS3
• Windows: AppData\Roaming\QGIS\QGIS3
• macOS: Library/Application Support/QGIS/QGIS3
Las rutas predeterminada del sistema dependen del sistema operativo. Para encontrar las rutas que funcionan para
usted, abra la consola de Python y ejecute [Link](QStandardPaths.
AppDataLocation) para ver la lista de directorios por defecto.
El script [Link] se ejecuta inmediatamente después de inicializar python en QGIS, al inicio de la aplicación.
Al configurar la variable de entorno PYQGIS_STARTUP con la ruta de un fichero Python existente, puede ejecutar
código Python justo antes de que la inicialización de QGIS se haya completado.
Este código se ejecutará antes de que se complete la inicialización de QGIS. Este método es muy útil para la limpieza
de [Link], que puede tener rutas no deseables, o para aislar/cargar el entorno inicial sin necesidad de un entorno
virtual, por ejemplo, homebrew o MacPorts se instala en Mac.
Puede proporcionar código personalizado para ejecutar como parámetro de inicio a QGIS. Para ello, cree un archivo
python, por ejemplo qgis_init.py, para ejecutar e iniciar QGIS desde la línea de comandos utilizando qgis
--code qgis_init.py.
El código proporcionado a través de --code se ejecuta al final de la fase de inicialización de QGIS, después de que
se hayan cargado los componentes de la aplicación.
Para proporcionar argumentos adicionales para tu script --code o para otro código python que se ejecute, puedes
usar el argumento --py-args. Cualquier argumento que venga después de --py-args y antes de -- arg (si está
presente) será pasado a Python pero ignorado por la propia aplicación QGIS.
En el siguiente ejemplo, [Link] estará disponible a través de [Link] en Python pero no será cargado
por QGIS. Mientras que [Link] será cargado por QGIS pero no está presente en [Link].
Si quiere acceder a todos los parámetros de la línea de comandos desde Python, puedes utilizar
[Link]().
[Link]().arguments()
A menudo es útil crear scripts para automatizar procesos. Con PyQGIS, esto es perfectamente posible — importe el
módulo [Link], Inicialícelo y estará listo para el procesamiento.
O tal vez desee crear una aplicación interactiva que utilice la funcionalidad GIS — realizar mediciones, exportar un
mapa como PDF, … El módulo [Link] proporciona varios componentes GUI, en particular el widget de lienzo del
mapa que se puede incorporar a la aplicación con soporte para hacer zoom, paneo y/o cualquier otra herramienta de
mapa personalizada.
Las aplicaciones personalizadas de PyQGIS o los scripts independientes deben configurarse para localizar los recursos
QGIS, como la información de proyección y los proveedores para leer capas vectoriales y ráster. Los recursos de
QGIS se inician añadiendo unas pocas líneas al principio de su aplicación o script. El código para inicializar QGIS
para aplicaciones personalizadas y scripts independientes es similar. A continuación se proporcionan ejemplos de
cada uno de ellos.
Nota: No utilice [Link] como nombre para su script. Python no podrá importar los enlaces, ya que el nombre
del script será su sombra.
Para iniciar un script independiente, inicialice los recursos QGIS al principio del script:
10 # Load providers
11 [Link]()
12
6 Capítulo 1. Introducción
PyQGIS 3.40 developer cookbook
Primero importa el módulo [Link] y configura el prefijo de ruta. El prefijo de ruta es la ubicación donde
está instalado QGIS en su sistema. Se configura en el script llamando al método setPrefixPath(). El
segundo argumento de setPrefixPath() es establecido a True, especificando que se utilizarán las rutas
predeterminadas.
La ruta de instalación de QGIS varía según la plataforma; la forma más fácil de encontrarlo para su sistema es usar
Desarrollar scripts en la consola de Python desde dentro de QGIS y ver el resultado de ejecutar:
[Link]()
Una vez configurada la ruta del prefijo, guardamos una referencia a QgsApplication en la variable qgs. El
segundo argumento está establecido como False, especificando que no planeamos usar la GUI ya que estamos
escribiendo un script independiente. Con QgsApplication configurado, cargamos los proveedores de datos de
QGIS y el registro de capas llamando al método initQgis().
[Link]()
Con QGIS inicializado, estamos listos para escribir el resto del script. Finalmente, terminamos llamando a
exitQgis() para eliminar los proveedores de datos y el registro de capas de la memoria.
[Link]()
La única diferencia entre Usando PyQGIS en scripts individuales y una aplicación PyQGIS personalizada es el segundo
argumento al crear una instancia del QgsApplication. Pase True en lugar de False para indicar que planeamos
utilizar una IGU.
12 # load providers
13 [Link]()
14
Ahora puede trabajar con la API de QGIS - carga de capas y realizar algún procesamiento o encender una GUI con
un lienzo de mapa. Las posibilidades son infinitas :-)
Necesita indicar a su sistema dónde buscar las bibliotecas QGIS y módulos de Python apropiados si no están en una
ubicación conocida - de lo contrario Python se quejará:
Esto se puede solucionar estableciendo la variable de entorno PYTHONPATH . En los siguientes comandos,
<qgispath> deberá ser reemplazado con su ruta de instalación de QGIS actual:
• en Linux: export PYTHONPATH=/<qgispath>/share/qgis/python
• en Windows: set PYTHONPATH=c:\<qgispath>\python
• en macOS: export PYTHONPATH=/<qgispath>/Contents/Resources/python
Ahora, se conoce la ruta de acceso a los módulos PyQGIS, pero dependen de las bibliotecas qgis_core y
qgis_gui (los módulos de Python solo sirven como contenedores). La ruta de acceso a estas bibliotecas puede
ser desconocida para el sistema operativo, y luego obtendrá un error de importación de nuevo (el mensaje puede
variar dependiendo del sistema):
Para solucionar, agregar los directorios donde residen las bibliotecas QGIS a la ruta de búsqueda del
enlazador dinámico:
• en Linux: export LD_LIBRARY_PATH=/<qgispath>/lib
• en Windows: set PATH=C:\<qgispath>\bin;C:\<qgispath>\apps\<qgisrelease>\
bin;%PATH% donde <qgisrelease> debe ser reemplazado por el tipo de enlace apuntado (por ejemplo:
qgis-ltr, qgis, qgis-dev)
Estos comandos se pueden poner en un script de arranque que se encargará del inicio. Al implementar aplicaciones
personalizadas con PyQGIS, normalmente hay dos posibilidades:
• requiere que el usuario instale QGIS antes de instalar la aplicación. El instalador de la aplicación debe buscar
ubicaciones predeterminadas de las bibliotecas QGIS y permitir al usuario establecer la ruta si no se encuentra.
Este enfoque tiene la ventaja de ser más sencillo, sin embargo, requiere que el usuario haga más pasos.
• paquete QGIS junto con su aplicación. Lanzar la aplicación puede ser más difícil y el paquete será más grande,
pero el usuario se salvará de la carga de descargar e instalar piezas adicionales de software.
Los dos modelos de implementación pueden ser mixtos. Puede proporcionar aplicaciones independientes en Windows
y macOS, pero para Linux dejar la instalación de SIG en manos del usuario y su administrador de paquetes.
Se ha decidido por Python, ya que es uno de los lenguajes más favoritos para el scripting. Los enlaces PyQGIS en
QGIS 3 dependen de SIP y PyQt5. La razón para usar SIP en lugar del ampliamente utilizado SWIG es que el código
QGIS depende de las bibliotecas Qt. Los enlaces de Python para Qt (PyQt) se realizan utilizando SIP y esto permite
la integración perfecta de PyQGIS con PyQt.
8 Capítulo 1. Introducción
CAPÍTULO 2
Cargar proyectos
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
Algunas veces se necesita cargar un proyecto existente desde un complemento o (más a menudo) al desarrollar una
aplicación autónoma QGIS Python (vea : Aplicaciones Python).
Para cargar un proyecto en la aplicación QGIS actual, debe crear una instancia de la clase QgsProject. Esta es una
clase singleton, por lo tanto se debe usar el método instance() para realizarlo. Puede llamar su método read()
y pasar la ruta para que el proyecto sea cargado:
1 # If you are not inside a QGIS console you first need to import
2 # qgis and PyQt classes you will use in this script as shown below:
3 from [Link] import QgsProject
4 # Get the project instance
5 project = [Link]()
6 # Print the current project file name (might be empty in case no projects have␣
,→been loaded)
7 # print([Link]())
8
testdata/01_project.qgs
Si necesita hacer modificaciones a su proyecto (por ejemplo añadir o remover algunas capas) y guardar los cambios
realizados, puede llamar el método write() de su instancia de proyecto. El método write() también acepta una
9
PyQGIS 3.40 developer cookbook
Las funciones read() y write() retornan un valor booleano que puede utilizar para verificar si la operación fue
exitosa.
Nota: Si está desarrollando una aplicación QGIS autónoma, para poder mantener la sincronización
entre el proyecto cargado y el lienzo, debe instanciar una :class:”QgsLayerTreeMapCanvasBridge
<[Link]>” al igual que en el ejemplo:
bridge = QgsLayerTreeMapCanvasBridge( \
[Link]().layerTreeRoot(), canvas)
# Now you can safely load your project and see it in the canvas
[Link]('testdata/my_new_qgis_project.qgs')
Puede suceder que las capas cargadas en el proyecto se muevan a otra ubicación. Cuando el proyecto se vuelve a
cargar, todas las rutas de las capas se rompen. La clase QgsPathResolver le ayuda a reescribir la ruta de las
capas dentro del proyecto.
Su método setPathPreprocessor() permite configurar una función de preprocesador de ruta personalizada
para manipular rutas y fuentes de datos antes de resolverlas en referencias de archivos o fuentes de capas.
La función del procesador debe aceptar un único argumento de cadena (que represente la ruta del archivo original o
la fuente de datos) y devolver una versión procesada de esta ruta. La función de preprocesador de ruta se llama antes
de cualquier controlador de capa defectuoso. Si se configuran varios preprocesadores, se llamarán en secuencia según
el orden en que se configuraron originalmente.
Algunos casos de uso:
1. reemplazar ruta desactualizada:
def my_processor(path):
return [Link]('c:/Users/ClintBarton/Documents/Projects', 'x:/
,→Projects/')
[Link](my_processor)
def my_processor(path):
return [Link]('host=[Link]', 'host=[Link]')
[Link](my_processor)
1 def my_processor(path):
2 path= [Link]("user='gis_team'", "user='team_awesome'")
3 path = [Link]("password='cats'", "password='g7as!m*'")
4 return path
5
6 [Link](my_processor)
Del mismo modo, un método setPathWriter() está disponible para una función de escritor de ruta.
Un ejemplo para reemplazar la ruta con una variable:
def my_processor(path):
return [Link]('c:/Users/ClintBarton/Documents/Projects', '$projectdir$')
[Link](my_processor)
Ambos métodos devuelven un id que se puede usar para eliminar el preprocesador o escritor que agregaron. Consulte
removePathPreprocessor() y removePathWriter().
En algunos casos en los que puede que no necesite utilizar un proyecto completamente funcional, pero sólo desea
acceder a él por una razón específica, las banderas pueden ser útiles. Una lista completa de banderas está disponible
en ProjectReadFlag. Se pueden añadir varias banderas juntas.
Por ejemplo, si no nos importan las capas y los datos reales y simplemente queremos acceder a un proyecto (por
ejemplo, para el diseño o la configuración de la vista 3D), podemos utilizar la bandera DontResolveLayers
para omitir el paso de validación de datos y evitar que aparezca el diálogo de capa incorrecta. Se puede hacer lo
siguiente:
readflags = [Link]()
readflags |= [Link]
project = [Link]()
[Link]('C:/Users/ClintBarton/Documents/Projects/[Link]',␣
,→readflags)
Para añadir más banderas se debe utilizar el operador Bitwise OR de python (|).
Cargar capas
Consejo: Los fragmentos de código en esta página necesitan las siguientes importaciones:
import os # This is is needed in the pyqgis console also
from [Link] import (
QgsVectorLayer
)
Vamos a abrir algunas capas con datos. QGIS reconoce capas vectoriales y ráster. Además, están disponibles tipos
de capas personalizadas, pero no se va a discutir de ellas aquí.
Para crear y añadir una instancia de capa vectorial al proyecto, especifique el identificador de fuente de datos de la
capa. El identificador de fuente de datos es una cadena y es específico de cada proveedor de datos vectoriales. Se
utiliza un nombre de capa opcional para identificar la capa en el panel Capas. Es importante comprobar si la capa se
ha cargado correctamente. Si no es así, se devuelve una instancia de capa no válida.
Para una capa vectorial creada mediante un geopackage:
1 # get the path to a geopackage
2 path_to_gpkg = "testdata/data/[Link]"
3 # append the layername part
4 gpkg_airports_layer = path_to_gpkg + "|layername=airports"
5 vlayer = QgsVectorLayer(gpkg_airports_layer, "Airports layer", "ogr")
6 if not [Link]():
7 print("Layer failed to load!")
8 else:
9 [Link]().addMapLayer(vlayer)
La forma más rápida de abrir y mostrar una capa vectorial en QGIS es el método addVectorLayer() de la clase
QgisInterface:
vlayer = [Link](gpkg_airports_layer, "Airports layer", "ogr")
if not vlayer:
print("Layer failed to load!")
13
PyQGIS 3.40 developer cookbook
Esto crea una nueva capa y la añade al actual proyecto QGIS (haciéndola aparecer en el listado de capas) en un solo
paso. La función retorna la instancia de capa o None` si es que no puede cargarla.
La siguiente lista muestra cómo acceder a varias fuentes de datos utilizando los proveedores de datos vectoriales:
• El proveedor ogr de la biblioteca GDAL soporta una amplia variedad de formatos, también llamados drivers en
el lenguaje GDAL. Algunos ejemplos son ESRI Shapefile, Geopackage, Flatgeobuf, Geojson, … Para formatos
de un solo archivo, la ruta del archivo suele ser suficiente como uri. Para geopackages o dxf, un sufijo separado
por una tubería permite especificar la capa a cargar.
– para Shapefile de ESRI:
uri = "testdata/[Link]"
vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr")
[Link]().addMapLayer(vlayer)
– para Geopackage (tenga en cuenta las opciones internas en la uri de la fuente de datos):
uri = "testdata/data/[Link]|layername=airports"
vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr")
[Link]().addMapLayer(vlayer)
– Para dxf (tenga en cuenta las opciones internas en la fuente de datos uri):
uri = "testdata/[Link]|layername=entities|geometrytype=Polygon"
vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr")
[Link]().addMapLayer(vlayer)
• Base de datos PostGIS - la fuente de datos es una cadena de texto con toda la información necesaria para crear
una conexión con la base de datos PostgreSQL.
La clase QgsDataSourceUri puede generar esta cadena de texto para usted. Tenga en cuenta que QGIS
debe compilarse con el soporte de Postgres, o de lo contrario, este proveedor no estará disponible:
1 uri = QgsDataSourceUri()
2 # set host name, port, database name, username and password
3 [Link]("localhost", "5432", "dbname", "johny", "xxx")
4 # set database schema, table name, geometry column and optionally
5 # subset (WHERE clause)
6 [Link]("public", "roads", "the_geom", "cityid = 2643", "primary_key_
,→field")
• CSV u otros archivos de texto delimitados — para abrir un archivo con un punto y coma como delimitador,
con el campo «x» para la coordenada X y el campo «y» para la coordenada Y, usaría algo como esto:
uri = "[Link]
,→format([Link](), ";", "x", "y")
Nota: La cadena de proveedor está estructurada como una dirección URL, por lo que la ruta de acceso debe ir
precedida de [Link] También permite geometrías en formato WKT (texto bien conocido) como alternativa
a los campos “”x”” y “”y””, y permite especificar el sistema de referencia de coordenadas. Por ejemplo:
uri = "[Link]
,→format(";", "shape")
• Los archivos GPX — el proveedor de datos «gpx» lee los caminos, rutas y puntos de interés desde archivos
GPX. Para abrir un archivo, el tipo (caminos/ruta/punto de interés) se debe especificar como parte de la url:
uri = "testdata/[Link]?type=track"
vlayer = QgsVectorLayer(uri, "layer name you like", "gpx")
[Link]().addMapLayer(vlayer)
• La base de datos SpatiaLite — De forma similar a las bases de datos PostGIS, :class:”QgsDataSourceUri
<[Link]>” puede ser utilizado para la generación de identificador de origen de datos:
1 uri = QgsDataSourceUri()
2 [Link]('/home/martin/[Link]')
3 schema = ''
4 table = 'Towns'
5 geom_column = 'Geometry'
6 [Link](schema, table, geom_column)
7
8 display_name = 'Towns'
9 vlayer = QgsVectorLayer([Link](), display_name, 'spatialite')
10 [Link]().addMapLayer(vlayer)
• Geometrías basadas en MySQL WKB, a través de GDAL — la fuente de datos es la cadena de conexión a la
tabla:
uri = "MySQL:dbname,host=localhost,port=3306,user=root,
,→password=xxx|layername=my_table"
• Conexión WFS: La conexión se define con un URL y usando el proveedor `` WFS “”:
uri = "[Link]
,→request=GetFeature&typename=ms:cities"
1 import urllib
2
3 params = {
4 'service': 'WFS',
5 'version': '2.0.0',
6 'request': 'GetFeature',
7 'typename': 'ms:cities',
8 'srsname': "EPSG:4326"
9 }
10 uri2 = '[Link] + [Link](urllib.
,→[Link](params))
Nota: Puede cambiar la fuente de datos de una capa existente llamando a setDataSource() en una instancia
de QgsVectorLayer, como se muestra a continuación ejemplo:
1 uri = "[Link]
,→request=GetFeature&typename=ms:cities"
2 provider_options = [Link]()
3 # Use project's transform context
(continúe en la próxima página)
7 del(vlayer)
Para acceder a un archivo raster, se utiliza la librería GDAL. Esta soporta un amplio rango de formatos de archivo. En
caso de que tenga problemas al abrir algún archivo, compruebe si es que su GDAL tiene soporte para el formato en
particular (no todos los formatos están disponibles de forma predeterminada). Para cargar un raster desde un archivo,
especifique el nombre del archivo y su nombre de visualización:
8 if not [Link]():
9 print("Layer failed to load!")
De manera similar a las capas vectoriales, las capas raster pueden ser cargadas utilizando la función addRasterLayer
de un objeto perteneciente a QgisInterface
Esto crea una nueva capa y la añade al proyecto actual (haciendo que aparezca en la lista) en un solo paso.
Para cargar un ráster PostGIS:
Los rásteres PostGIS, similares a los vectores PostGIS, se pueden agregar a un proyecto mediante una cadena URI.
Es eficaz mantener un diccionario de cadenas reutilizable para los parámetros de conexión de la base de datos.
Esto facilita la edición del diccionario para la conexión correspondiente. Luego, el diccionario se codifica en un
URI utilizando el objeto de metadatos del proveedor “postgresraster”. Después de eso, el ráster se puede agregar al
proyecto.
1 uri_config = {
2 # database parameters
3 'dbname':'gis_db', # The PostgreSQL database to connect to.
4 'host':'localhost', # The host IP address or localhost.
5 'port':'5432', # The port to connect on.
6 'sslmode':[Link], # SslAllow, SslPrefer, SslRequire,␣
,→SslVerifyCa, SslVerifyFull
7 # user and password are not needed if stored in the authcfg or service
8 'authcfg':'QconfigId', # The QGIS athentication database ID holding␣
,→connection details.
27 }
28 # remove any NULL parameters
29 uri_config = {key:val for key, val in uri_config.items() if val is not None}
30 # get the metadata for the raster provider and configure the URI
31 md = [Link]().providerMetadata('postgresraster')
32 uri = QgsDataSourceUri([Link](uri_config))
33
layer_name = 'modis'
url = "[Link]
rlayer = QgsRasterLayer(uri, 'my wcs layer', 'wcs')
Aquí está una descripción de los parámetros que el WCS URI puede contener:
El WCS URI se compone de pares calve=valor separadas por &. Es el mismo formato que la cadena de consulta en la
URL, codificada de la misma manera. QgsDataSourceUri debe utilizarse para construir el URI para garantizar
que los caracteres especiales se codifican correctamente.
• url (requerido) : URL del servidor WCS. No utilice la VERSION en el URL, porque cada versión del WCS
está usando nombre de parámetro diferente para la versión de GetCapabilities vea la versión del parámetro.
• identifier (requerido) : Nombre de la Cobertura
• time (opcional) : posición de tiempo o período de tiempo (beginPosition/endPosition[/timeResolution])
• format (opcional) : Nombre de formato admitido. El valor predeterminado es el primer formato compatible
con el nombre en tif o el primer formato compatible.
• crs (opcional): CRS en el formato AUTORIDAD:IDENTIFICADOR, p. ej. EPSG:4326. El valor
predeterminado es EPSG:4326, si es que es compatible, o si no el primer CRS compatible.
• nombre de usuario (opcional): Nombre de usuario para la autenticación básica.
• contraseña (opcional): Contraseña para la autenticación básica.
• IgnoreGetMapUrl (opcional, hack): si se especifica (establecido en 1), ignore la dirección URL de
GetCoverage anunciada por GetCapabilities. Puede ser necesario si un servidor no está configurado
correctamente.
urlWithParams = "crs=EPSG:4326&format=image/png&layers=continents&styles&
,→url=[Link]
Si desea utilizar las capas abiertas para la representación, no olvide agregarlas a la instancia de QgsProject.
La instancia QgsProject toma la posesión de las capas y más adelante, se puede acceder desde cualquier parte
de la aplicación mediante su identificador único . Cuando la capa se elimina del proyecto, también se elimina.
Las capas pueden ser eliminadas por el usuario en la interfaz QGIS, o a través de Python usando el método
removeMapLayer().
Añadir una capa al proyecto actual, se puede realizar, utilizando el método addMapLayer() :
[Link]().addMapLayer(rlayer)
# [Link]().removeMapLayer(layer_id)
[Link]().removeMapLayer([Link]())
En el código anterior, el identificador de la capa es pasado (puede obtenerlo llamando el método id() que pertenece
a la capa), pero también puede hacerlo pasando el objeto capa en si mismo.
Para una lista de capas cargadas y sus identificadores, use el método mapLayers() :
[Link]().mapLayers()
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
from [Link] import (
QgsProject,
QgsVectorLayer,
)
Puede usar diferentes clases para acceder a todas las capas cargadas en la TOC y usarlas para obtener información:
• QgsProject
• QgsLayerTreeGroup
Puede usar la clase QgsProject para recuperar información sobre la TOC y todas las capas cargadas.
Debe crear una instance de QgsProject y usar sus métodos para obtener las capas cargadas.
El método principal es mapLayers(). Devolverá un diccionario con las capas cargadas:
layers = [Link]().mapLayers()
print(layers)
Las claves del diccionario son las ids únicas de capa mientras que los valores son los objetos relacionados.
Ahora es sencillo obtener cualquier otra información sobre las capas:
1 # list of layer names using list comprehension
2 l = [[Link]() for layer in [Link]().mapLayers().values()]
3 # dictionary with key = layer name and value = layer object
4 layers_list = {}
(continúe en la próxima página)
19
PyQGIS 3.40 developer cookbook
8 print(layers_list)
Nota: Se devuelve una lista con todas las capas coincidentes, por lo que indexamos con [0] para obtener la primera
capa con este nombre.
La capa árbol es una estructura clásica de árbol construida con nodos. Hay actualmente dos tipos de nodos: nodos de
grupo (QgsLayerTreeGroup) y nodos de capa (QgsLayerTreeLayer).
Nota: for more information you can read these blog posts of Martin Dobias: Part 1 Part 2 Part 3
Se puede acceder fácilmente al árbol de capas del proyecto con el método layerTreeRoot() de la clase
QgsProject:
root = [Link]().layerTreeRoot()
Se devuelve una lista de hijos directos. Se debe acceder a los hijos del subgrupo desde su propio padre directo.
Podemos recuperar uno de los hijos:
child0 = [Link]()[0]
print(child0)
<QgsLayerTreeLayer: countries>
QgsLayerTreeGroup tiene muchos otros métodos útiles que se pueden utilizar para obtener más información
sobre el TOC:
# list of all the checked layers in the TOC
checked_layers = [Link]()
print(checked_layers)
Ahora agreguemos algunas capas al árbol de capas del proyecto. Hay dos formas de hacerlo:
1. Adición explícita usando las funciones addLayer() o insertLayer():
1 # create a temporary layer
2 layer1 = QgsVectorLayer("path_to_layer", "Layer 1", "memory")
3 # add the layer to the legend, last position
4 [Link](layer1)
5 # add the layer at given position
6 [Link](5, layer1)
2. Adición implícita: dado que el árbol de capas del proyecto está conectado al registro de capas, basta con
agregar una capa al registro de capas del mapa:
[Link]().addMapLayer(layer1)
Los grupos pueden ser añadidos con el método addGroup(). En el siguiente ejemplo, el primero agregará un grupo
al final de la tabla de contenido, mientras que para el segundo puede agregar otro grupo dentro de uno existente:
node_group1 = [Link]('Simple Group')
# add a sub-group to Simple Group
node_subgroup1 = node_group1.addGroup("I'm a sub group")
1 # get a QgsVectorLayer
2 vl = [Link]().mapLayersByName("countries")[0]
3 # create a QgsLayerTreeLayer object from vl by its id
4 myvl = [Link]([Link]())
5 # clone the myvl QgsLayerTreeLayer object
6 myvlclone = [Link]()
7 # create a new group
8 group1 = [Link]("Group1")
9 # get the parent. If None (layer is not in group) returns ''
10 parent = [Link]()
11 # move the cloned layer to the top (0)
12 [Link](0, myvlclone)
13 # remove the QgsLayerTreeLayer from its parent
14 [Link](myvl)
Algunos otros métodos que se pueden utilizar para modificar los grupos y capas:
1 node_group1 = [Link]("Group1")
2 # change the name of the group
3 node_group1.setName("Group X")
4 node_layer2 = [Link](country_layer.id())
5 # change the name of the layer
6 node_layer2.setName("Layer X")
7 # change the visibility of a layer
8 node_group1.setItemVisibilityChecked(True)
9 node_layer2.setItemVisibilityChecked(False)
10 # expand/collapse the group view
11 node_group1.setExpanded(True)
12 node_group1.setExpanded(False)
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
Una capa ráster está compuesta por una o más bandas ráster — denominadas como raster monobanda o multibanda.
Una banda representa una matriz de valores. Una imagen a color (p. ej. una fotografía aérea) es un ráster que está
constituido por bandas roja, azul y verde. Los rásteres de banda única, representan generalmente variables continuas
(p. ej. elevación) o variables discretas (p. ej. uso del suelo). En algunos casos, una capa ráster viene con una paleta y
los valores ráster se refieren a los colores almacenados en la paleta.
El código a continuación, asume que rlayer es un objeto de QgsRasterLayer .
rlayer = [Link]().mapLayersByName('srtm')[0]
# get the resolution of the raster in layer unit
print([Link](), [Link]())
23
PyQGIS 3.40 developer cookbook
919 619
20.0685680819999988,-34.2700107699999990 : 20.8394528430000001,-33.7507750070000014
print([Link]())
Band 1: Height
5.2 Renderizador
Cuando una capa ráster es cargada, recibe en base a su tipo, el valor del renderizador de forma predeterminada. Esto
puede ser modificado tanto en las propiedades de capa o mediante programación.
Para consultar el actual renderizador:
print([Link]())
print([Link]().type())
singlebandgray
Para establecer un renderizador, use el método setRenderer() de QgsRasterLayer. Hay una serie de clases
de renderizado (derivadas de QgsRasterRenderer):
• QgsHillshadeRenderer
• QgsMultiBandColorRenderer
• QgsPalettedRasterRenderer
• QgsRasterContourRenderer
• QgsSingleBandColorDataRenderer
• QgsSingleBandGrayRenderer
• QgsSingleBandPseudoColorRenderer
Las capas ráster de banda única pueden ser dibujadas tanto en colores grises (valor menor = negro, valor alto = blanco)
o con un algoritmo pseudocolor que asigna colores a los valores. Rásters de banda única con una paleta puedes ser
dibujados usando la paleta. Las capas multibanda generalmente se dibujan asignando las bandas a colores RGB. Otra
posibilidad es usar una sola banda para dibujar.
Supongamos que queremos renderizar una capa ráster de una sola banda con colores que van del verde al amarillo
(correspondiente a los valores de píxel de 0 a 255). En la primera etapa prepararemos un objeto QgsRasterShader
y configuraremos su función shader:
1 fcn = QgsColorRampShader()
2 [Link]([Link])
3 lst = [ [Link](0, QColor(0,255,0)),
4 [Link](255, QColor(255,255,0)) ]
5 [Link](lst)
6 shader = QgsRasterShader()
7 [Link](fcn)
El sombreador asigna los colores según lo especificado por su mapa de colores. El mapa de colores es proveído como
una lista de valores de pixeles con colores asociados. Hay tres modos de interpolación:
• lineal (Interpolated): el color es linealmente interpolado desde las entradas en el mapa de colores, que
están por encima y por debajo de el valor de pixel.
• discreto (Discrete): el color es tomado desde la entrada más cercana con igual o mayor valor en el mapa de
colores.
• exacto (Exact): el color no es interpolado, solo los pixeles con un valor igual a las entradas del mapa de colores
serán dibujados.
En el segundo paso asociaremos el sombreador con una capa ráster:
El número 1 en el código anterior es el número de la banda (bandas ráster son indexadas de uno).
Finálmente tenemos que usar el método triggerRepaint() para ver los resultados:
[Link]()
5.2. Renderizador 25
PyQGIS 3.40 developer cookbook
De forma predeterminada, QGIS asigna las tres primeras bandas a rojo, verde y azul para crear una imagen en color
(este es el estilo de dibujo MultiBandColor). En algunos casos, es posible que desee anular esta configuración.
El siguiente código intercambia la banda roja (1) y la banda verde (2):
rlayer_multi = [Link]().mapLayersByName('multiband')[0]
rlayer_multi.renderer().setGreenBand(1)
rlayer_multi.renderer().setRedBand(2)
En caso de que sea necesaria solo una banda para la visualización del ráster, se puede elegir el dibujo de una banda
única, ya sea niveles grises o pseudocolor.
Tenemos que usar triggerRepaint() para actualizar el mapa y ver el resultado:
rlayer_multi.triggerRepaint()
Los valores rster ´pueden ser consultados usando el método sample() de la clase QgsRasterDataProvider
. Tienes que especificar una QgsPointXY y el número de banda de la capa ráster que quiera consultar. El método
devuelve una tupla con el valor y True o False dependiendo del resultado:
Otro método para consultar valores ráster es usar el método identify() que devuelve un objeto
QgsRasterIdentifyResult.
if [Link]():
print([Link]())
{1: 323.0}
En este caso, el método results() devuelve un diccionario, con el índice de banda como clave, y valores de banda
como valores. Por ejemplo, algo como {1: 323.0}
Puede crear una capa ráster utilizando la clase QgsRasterBlock. Por ejemplo, para crear un bloque ráster de 2x2
con un byte por píxel:
block = QgsRasterBlock([Link], 2, 2)
[Link](b'\xaa\xbb\xcc\xdd')
Los píxeles de trama se pueden sobrescribir gracias al método writeBlock(). Para sobrescribir datos ráster
existentes en la posición 0,0 por el bloque 2x2:
provider = [Link]()
[Link](True)
[Link](block, 1, 0, 0)
[Link](False)
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
27
PyQGIS 3.40 developer cookbook
Esta sección sumariza varias acciones que pueden ser realizadas con las capas vectoriales
La mayor parte del trabajo acá expuesto está basado en los métodos de la clase QgsVectorLayer.
Puede recuperar información sobre los campos asociados a una capa vectorial llamando el método fields() de
un objeto de la clase QgsVectorLayer
1 fid Integer64
2 id Integer64
3 scalerank Integer64
4 featurecla String
5 type String
6 name String
7 abbrev String
8 location String
9 gps_code String
10 iata_code String
11 wikipedia String
12 natlscale Real
print([Link]())
name
Nota: Si cambia el Nombre de Visualización de un campo a una expresión, tiene que usar
displayExpression() en vez de displayField().
a iteración de las entidades de una capa vectorial es una de las tareas más comunes. A continuación se muestra un
ejemplo del código básico simple para realizar esta tarea y mostrar cierta información sobre cada característica. Se
supone que la variable “”layer”” tiene un objeto QgsVectorLayer.
Feature ID: 1
Point: <QgsPointXY: POINT(7 45)>
[1, 'First feature']
En el escritorio QGIS, las entidades se pueden seleccionar de diferentes maneras: el usuario puede hacer clic en una
entidad, dibujar un rectángulo en el lienzo del mapa o utilizar un filtro de expresión. Las entidades seleccionadas
normalmente se resaltan en un color diferente (el valor predeterminado es el amarillo) para llamar la atención del
usuario sobre la selección.
A veces puede ser útil seleccionar características mediante programación o cambiar el color predeterminado.
Para seleccionar todas las características, se puede utilizar el método selectAll()
# Get the active layer (must be a vector layer)
layer = [Link]()
[Link]()
Para cambiar el color de selección puede utilizar el método setSelectionColor() de QgsMapCanvas como
se muestra en el ejemplo siguiente:
[Link]().setSelectionColor( QColor("red") )
Para agregar entidades a la lista de entidades seleccionada para una capa determinada, puede llamar a select()
pasándole la lista de identificadores de las entidades:
1 selected_fid = []
2
[Link]()
print(feature['name'])
First feature
Alternativamente, se puede hacer referencia a los atributos por índice. Esto es un poco más rápido que usar el nombre.
Por ejemplo, para obtener el segundo atributo:
print(feature[1])
First feature
Si solo necesita entidades seleccionadas, puede utilizar el método selectedFeatures() de la capa vectorial:
selection = [Link]()
for feature in selection:
# do whatever you need with the feature
pass
Si desea iterar sobre un subconjunto determinado de entidades de una capa, como las que se encuentran en un
área determinada, debe agregar un objeto QgsFeatureRequest a la llamada de getFeatures(). Este es
un ejemplo:
3 request = QgsFeatureRequest().setFilterRect(areaOfInterest)
4
En aras de la velocidad, la intersección a menudo se realiza solo con el cuadro delimitador de la entidad. Sin embargo,
hay una bandera ExactIntersect que se asegura de que solo se devolverán las entidades que se cruzan:
request = QgsFeatureRequest().setFilterRect(areaOfInterest) \
.setFlags([Link])
request = QgsFeatureRequest()
[Link](2)
for feature in [Link](request):
print(feature)
Si necesita un filtro basado en atributos en su lugar (o además) de uno espacial como se muestra en los ejemplos
anteriores, puede crear un objeto QgsExpression y pasarlo al constructor QgsFeatureRequest. Este es un
ejemplo:
# The expression will filter the features where the field "location_name"
# contains the word "Lake" (case insensitive)
exp = QgsExpression('location_name ILIKE \'%Lake%\'')
request = QgsFeatureRequest(exp)
Consulte Expresiones, Filtros y Calculando Valores para obtener detalles sobre la sintaxis admitida por
QgsExpression.
La solicitud se puede utilizar para definir los datos recuperados para cada entidad, por lo que el iterador devuelve
todas las entidades, pero devuelve datos parciales para cada una de ellas.
La mayoría de los proveedores de datos vectoriales admiten la edición de datos de capa. A veces solo admiten un
subconjunto de posibles acciones de edición. Utilice la función capabilities() para averiguar qué conjunto de
funcionalidad es compatible.
caps = [Link]().capabilities()
# Check if a particular capability is supported:
if caps & [Link]:
print('The layer supports DeleteFeatures')
Para obtener una lista de todas las capacidades disponibles, consulte la documentación API Documentation of
QgsVectorDataProvider.
Para imprimir la descripción textual de las capacidades de las capas en una lista separada por comas, puede utilizar
capabilitiesString() como en el ejemplo siguiente:
1 caps_string = [Link]().capabilitiesString()
2 # Print:
3 # 'Add Features, Delete Features, Change Attribute Values, Add Attributes,
4 # Delete Attributes, Rename Attributes, Fast Access to Features at ID,
5 # Presimplify Geometries, Presimplify Geometries with Validity Check,
6 # Transactions, Curved Geometries'
Mediante el uso de cualquiera de los métodos siguientes para la edición de capas vectoriales, los cambios se confirman
directamente en el almacén de datos subyacente (un archivo, una base de datos, etc.). En caso de que desee realizar
solo cambios temporales, vaya a la siguiente sección que explica cómo hacer modificaciones con la edición de cambios
de búfer.
Nota: Si está trabajando dentro de QGIS (ya sea desde la consola o desde un complemento), podría ser necesario
forzar un redibujo del lienzo del mapa para ver los cambios que ha realizado en la geometría, en el estilo o en los
atributos:
Crea algunas instancias QgsFeature y pasa una lista de ellas al método QgsVectorDataProvider
addFeatures(). Devolverá dos valores: resultado (True o False) y lista de objetos espaciales añadidos (su
ID lo establece el almacén de datos).
Para configurar los atributos de la entidad, puede inicializar la entidad pasando un objeto QgsFields (puede
obtenerlo del método fields() de la capa vectorial) o llamar a initAttributes() pasando el número de
campos que desea agregar.
Para eliminar algunas entidades, solo tiene que proporcionar una lista de identificaciones de entidades.
Es posible cambiar la geometría de la entidad o cambiar algunos atributos. En el ejemplo siguiente se cambian primero
los valores de los atributos con los índices 0 y 1 y, a continuación, se cambia la geometría de la entidad.
Al editar vectores dentro de la aplicación QGIS, primero debe iniciar el modo de edición para una capa en particular,
luego hacer algunas modificaciones y finalmente confirmar (o deshacer) los cambios. Todos los cambios que realiza
no se escriben hasta que los confirma; permanecen en el búfer de edición en memoria de la capa. Es posible utilizar
esta funcionalidad también de forma programática, es solo otro método para la edición de capas vectoriales que
complementa el uso directo de los proveedores de datos. Use esta opción cuando proporcione algunas herramientas
GUI para la edición de capas vectoriales, ya que esto permitirá al usuario decidir si confirmar / deshacer y permite el
uso de deshacer/rehacer. Cuando se confirman los cambios, todos los cambios del búfer de edición se guardan en el
proveedor de datos.
Los métodos son similares a los que hemos visto en el proveedor, pero se llaman en el objeto QgsVectorLayer
en su lugar.
Para que estos métodos funcionen, la capa debe estar en modo de edición. Para iniciar el modo de edición, utilice el
método startEditing() Para detener la edición, utilice los métodos commitChanges() o rollBack().
El primero confirmará todos los cambios en el origen de datos, mientras que el segundo los descartará y no modificará
el origen de datos en absoluto.
Para averiguar si una capa está en modo de edición, utilice el método isEditable().
Aquí tiene algunos ejemplos que muestran cómo utilizar estos métodos de edición.
Para hacer que deshacer/rehacer trabaje correctamente, las llamadas mencionadas arriba tienen que ser envueltas
en los comandos undo. (Si no le importa deshacer/rehacer y desea que los cambios se almacenen inmediatamente,
entonces tendrá un trabajo más fácil por editando con proveedor de datos.)
Así es cómo usted puede utilizar la funcionalidad de deshacer:
1 [Link]("Feature triangulation")
2
5 if problem_occurred:
6 [Link]()
7 # ... tell the user that there was a problem
8 # and return
9
12 [Link]()
El método beginEditCommand() creará un comando interno de «activo» y registrará los cambios posteriores
en la capa vectorial. Con la llamada a el comando endEditCommand() se inserta en la pila de deshacer y el
usuario podrá deshacer/rehacerlo desde la GUI. En caso de que algo saliera mal al realizar los cambios, el método
destroyEditCommand() quitará el comando y revertirá todos los cambios realizados mientras este comando
estaba activo.
También puede utilizar la instrucción with edit(layer)- para encapsular la confirmación y la reversión en un
bloque de código más semántico, como se muestra en el ejemplo siguiente:
with edit(layer):
feat = next([Link]())
feat[0] = 5
[Link](feat)
Esto llamará automáticamente a commitChanges() al final. Si ocurre alguna excepción, hará rollBack() a
todos los cambios. En caso de que se encuentre un problema dentro de commitChanges() (cuando el método
devuelve False) se producirá una excepción QgsEditError.
Para agregar campos (atributos), usted necesita especificar una lista de definiciones de campo. Para la eliminación de
campos sólo proporcione una lista de índices de campo.
Después de agregar o quitar campos en el proveedor de datos, los campos de la capa deben actualizarse porque los
cambios no se propagan automáticamente.
[Link]()
Los índices espaciales pueden mejorar drásticamente el rendimiento del código si necesita realizar consultas frecuentes
en una capa vectorial. Imagine, por ejemplo, que está escribiendo un algoritmo de interpolación, y que para una
ubicación determinada necesita conocer los 10 puntos más cercanos de una capa de puntos, con el fin de utilizar esos
puntos para calcular el valor interpolado. Sin un índice espacial, la única manera de que QGIS encuentre esos 10
puntos es calcular la distancia desde todos y cada uno de los puntos hasta la ubicación especificada y luego comparar
esas distancias. Esto puede ser una tarea que consume mucho tiempo, especialmente si necesita repetirse para varias
ubicaciones. Si existe un índice espacial para la capa, la operación es mucho más efectiva.
Piense en una capa sin un índice espacial como una guía telefónica en la que los números de teléfono no se ordenan ni
indexan. La única manera de encontrar el número de teléfono de una persona determinada es leer desde el principio
hasta que lo encuentres.
Los índices espaciales no se crean de forma predeterminada para una capa vectorial QGIS, pero puede crearlos
fácilmente. Esto es lo que tienes que hacer:
index = QgsSpatialIndex()
• agregar entidades al índice — el índice toma el objeto QgsFeature y lo agrega a la estructura de datos
interna. Puede crear el objeto manualmente o usar uno de una llamada anterior al método getFeatures()
del proveedor.
[Link](feat)
• alternativamente, puede cargar todas las entidades de una capa a la vez utilizando la carga masiva
index = QgsSpatialIndex([Link]())
• Una vez que el índice espacial se llena con algunos valores, puede realizar algunas consultas
También puede usar el índice espacial QgsSpatialIndexKDBush. Este índice es similar al estándar
QgsSpatialIndex pero:
• soporta solo entidades de único punto
• es estática (no se pueden agregar entidades adicionales al índice después de la construcción)
• es ¡mas rápida!
• permite la recuperación directa de los puntos de la entidad original, sin requerir solicitudes de entidades
adicionales
• admite búsquedas verdaderas basadas en la distancia, es decir, devuelve todos los puntos dentro de un radio
desde un punto de búsqueda
La clase QgsVectorLayerUtils contiene algunos métodos muy útiles que puede utilizar con capas vectoriales.
Por ejemplo el método createFeature() prepara una QgsFeature para ser agregada a una capa vectorial
manteniendo todas las eventuales restricciones y valores predeterminados de cada campo:
feat = [Link](vlayer)
(['Sahnewal'], True)
También puede convertir campos para que sean compatibles con formatos diferentes usando
FieldValueConverter. Por ejemplo, para convertir tipos de variable matriz (por ejemplo, en Postgres)
en un tipo texto, puede hacer lo siguiente:
1 LIST_FIELD_NAME = 'xxxx'
2
3 class ESRIValueConverter([Link]):
4
8 """ create an instance of vector file writer, which will create the vector file.
9 Arguments:
10 1. path to new file (will fail if exists already)
11 2. field map
12 3. geometry type - from WKBTYPE enum
13 4. layer's spatial reference (instance of
14 QgsCoordinateReferenceSystem)
(continúe en la próxima página)
19 crs = [Link]().crs()
20 transform_context = [Link]().transformContext()
21 save_options = [Link]()
22 save_options.driverName = "ESRI Shapefile"
23 save_options.fileEncoding = "UTF-8"
24
25 writer = [Link](
26 "testdata/my_new_shapefile.shp",
27 fields,
28 [Link],
29 crs,
30 transform_context,
31 save_options
32 )
33
34 if [Link]() != [Link]:
35 print("Error when creating shapefile: ", [Link]())
36
37 # add a feature
38 fet = QgsFeature()
39
40 [Link]([Link](QgsPointXY(10,10)))
41 [Link]([1, "text"])
42 [Link](fet)
43
Entre todos los proveedores de datos admitidos por la clase QgsVectorLayer, vamos a centrarnos en las capas
basadas en memoria. Proveedor de memoria está destinado a ser utilizado principalmente por plugins o desarrolladores
de aplicaciones de 3as partes. No almacena datos en el disco, lo que permite a los desarrolladores utilizarlos como
un backend rápido para algunas capas temporales.
El proveedor admite los campos string, int y double.
El proveedor de memoria también admite la indexación espacial, que se habilita llamando a la función
createSpatialIndex() del proveedor. Una vez creado el índice espacial, podrá recorrer iterando sobre las
entidades dentro de regiones más pequeñas más rápido (ya que no es necesario atravesar todas las entidades, solo las
del rectángulo especificado)..
Un proveedor de memoria se crea pasando "memory" como la cadena del proveedor al constructor
QgsVectorLayer.
El constructor también toma un URI que define el tipo de geometría de la capa, uno de: "Point", "LineString",
"Polygon", "MultiPoint", "MultiLineString", "MultiPolygon" o "None".
El URI también puede especificar el sistema de referencia de coordenadas, los campos y la indexación del proveedor
de memoria en el URI. La sintaxis es:
crs=definition
Especifica el sistema de referencia de coordenadas, donde la definición puede ser cualquiera de las formas
aceptadas por [Link]()
index=yes
Especifica que el proveedor utilizará un índice espacial
field=name:type(length,precision)
Especifica un atributo de la capa. El atributo tiene un nombre y, opcionalmente, un tipo (entero, doble o cadena),
longitud y precisión. Puede haber múltiples definiciones de campo
El siguiente ejemplo de una URI incorpora todas estas opciones
"Point?crs=epsg:4326&field=id:integer&field=name:string(20)&index=yes"
3 # create layer
4 vl = QgsVectorLayer("Point", "temporary_points", "memory")
5 pr = [Link]()
6
7 # add fields
8 [Link]([QgsField("name", [Link]),
9 QgsField("age", [Link]),
10 QgsField("size", [Link])])
11 [Link]() # tell the vector layer to fetch changes from the provider
12
13 # add a feature
14 fet = QgsFeature()
15 [Link]([Link](QgsPointXY(10,10)))
16 [Link](["Johnny", 2, 0.3])
17 [Link]([fet])
18
fields: 3
features: 1
extent: 10.0 10.0 10.0 10.0
F: 1 ['Johnny', 2, 0.3] <QgsPointXY: POINT(10 10)>
Cuando una capa vectorial se representa, la apariencia de los datos se indica por renderer y símbolos asociados a la
capa. Los símbolos son clases que se encargan del dibujo de la representación visual de las entidades, mientras que
los renderizadores determinan qué símbolo se utilizará para una entidad determinada.
El renderizador para una capa determinada se puede obtener como se muestra a continuación:
renderer = [Link]()
print("Type:", [Link]())
Type: singleSymbol
También puede haber algunos tipos de presentadores personalizados, por lo que nunca haga una suposición de que
solo hay estos tipos. Puede consultar el QgsRendererRegistry de la aplicación para encontrar los presentadores
disponibles actualmente:
print([Link]().renderersList())
Es posible obtener un volcado del contenido de presentador en forma de texto — puede ser útil para la depuración
[Link]()
Puede obtener el símbolo utilizado para la representación llamando al método symbol() y cambiarlo con el
método :meth:`setSymbol() <[Link]>`(nota para desarrolladores de C++:
el renderizado toma posesión del símbolo.)
Puede cambiar el símbolo utilizado por una capa vectorial determinada llamando a setSymbol() pasando
una instancia de la instancia de símbolo apropiada. Los símbolos para las capas de point, line y polygon pueden
ser creadas llamando a la función createSimple() de las clases correspondientes QgsMarkerSymbol,
QgsLineSymbol y QgsFillSymbol.
El diccionario pasado a createSimple() establece las propiedades de estilo del símbolo.
Por ejemplo, puede reemplazar el símbolo utilizado por una capa point particular llamando a setSymbol()
pasando una instancia de QgsMarkerSymbol, como en el siguiente ejemplo de código:
name indica la forma del marcador, y puede ser cualquiera de los siguientes:
• circle
• square
• cross
• rectangle
• diamond
• pentagon
• triangle
• equilateral_triangle
• star
• regular_star
• arrow
• filled_arrowhead
• x
Para obtener la lista completa de propiedades de la primera capa de símbolos de una instancia de símbolo, puede
seguir el código de ejemplo:
print([Link]().symbol().symbolLayers()[0].properties())
,→'outline_color': '35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.
Al utilizar un representador categorizado, puede consultar y establecer el atributo que se utiliza para la clasificación:
utilice los métodos classAttribute() y setClassAttribute().
Para obtener una lista de categorías
1 categorized_renderer = QgsCategorizedSymbolRenderer()
2 # Add a few categories
3 cat1 = QgsRendererCategory('1', QgsMarkerSymbol(), 'category 1')
4 cat2 = QgsRendererCategory('2', QgsMarkerSymbol(), 'category 2')
5 categorized_renderer.addCategory(cat1)
6 categorized_renderer.addCategory(cat2)
7
Donde value() es el valor utilizado para la discriminación entre categorías, label() es el texto utilizado para la
descripción de la categoría y el método symbol() devuelve el símbolo asignado.
El renderizador suele almacenar también el símbolo original y la rampa de color que se utilizaron para la clasificación:
métodos sourceColorRamp() y sourceSymbol().
Este representador es muy similar al representador de símbolos categorizados descrito anteriormente, pero en lugar
de un valor de atributo por clase trabaja con rangos de valores y, por lo tanto, solo se puede utilizar con atributos
numéricos.
Para obtener más información sobre los rangos utilizados en el renderizador
1 graduated_renderer = QgsGraduatedSymbolRenderer()
2 # Add a few categories
3 graduated_renderer.addClassRange(QgsRendererRange(QgsClassificationRange('class 0-
,→100', 0, 100), QgsMarkerSymbol()))
4 graduated_renderer.addClassRange(QgsRendererRange(QgsClassificationRange('class␣
,→101-200', 101, 200), QgsMarkerSymbol()))
puedes volver a usar los métodos classAttribute() (para encontrar el nombre del atributo de clasificación),
sourceSymbol() y sourceColorRamp() . Adicionalmente está el método mode() que determina como
son creados los rangos: usando intervalos iguales, cuanties o algún otro método.
Si desea crear su propio renderizador de símbolos graduados, puede hacerlo como se ilustra en el siguiente fragmento
de ejemplo (que crea una sencilla disposición de dos clases)
3 myVectorLayer = QgsVectorLayer("testdata/data/[Link]|layername=airports",
,→"Airports layer", "ogr")
4 myTargetField = 'scalerank'
5 myRangeList = []
6 myOpacity = 1
7 # Make our first symbol and range...
8 myMin = 0.0
9 myMax = 50.0
10 myLabel = 'Group 1'
11 myColour = [Link]('#ffee00')
12 mySymbol1 = [Link]([Link]())
13 [Link](myColour)
14 [Link](myOpacity)
15 myRange1 = QgsRendererRange(myMin, myMax, mySymbol1, myLabel)
16 [Link](myRange1)
17 #now make another symbol and range...
18 myMin = 50.1
19 myMax = 100
20 myLabel = 'Group 2'
21 myColour = [Link]('#00eeff')
(continúe en la próxima página)
30 [Link](myClassificationMethod)
31 [Link](myTargetField)
32
33 [Link](myRenderer)
Para la representación de símbolos, hay esta clase base QgsSymbol con tres clases derivadas:
• QgsMarkerSymbol — para entidades de punto
• QgsLineSymbol — para entidades de línea
• QgsFillSymbol — para entidades de polígono
Cada símbolo consta de una o más capas de símbolos (clases derivadas de QgsSymbolLayer). Las capas de
símbolos hacen la representación real, la propia clase de símbolo sirve sólo como un contenedor para las capas de
símbolo.
Teniendo una instancia de un símbolo (por ejemplo, de un renderizador), es posible explorarlo: el método type()
dice si es un marcador, línea o símbolo de relleno . Hay un método dump() que devuelve una breve descripción del
símbolo. Para obtener una lista de capas de símbolos:
marker_symbol = QgsMarkerSymbol()
for i in range(marker_symbol.symbolLayerCount()):
lyr = marker_symbol.symbolLayer(i)
print("{}: {}".format(i, [Link]()))
0: SimpleMarker
Para averiguar el color del símbolo use el método color() y setColor() para cmabiar su color. Con los símbolos
de marcador, además, puede consultar el tamaño y la rotación del símbolo con los métodos size() y angle() .
Para símbolos lineales el método width() devuelve la anchura de la línea.
De forma predeterminada el tamaño y ancho están en milímetros, los ángulos en grados.
Como se dijo antes, las capas de símbolo (subclases de QgsSymbolLayer) determinar la apariencia de las
entidades. Hay varias clases de capas de símbolos básicas para uso general. Es posible implementar nuevos tipos de
capas de símbolos y así personalizar arbitrariamente cómo se renderizarán las entidades. El método layerType()
identifica de forma única la clase de capa de símbolo — las básicas y predeterminadas son los tipos de capas de
símbolo `` SimpleMarker “”, `` SimpleLine “” y `` SimpleFill “”.
identifica de forma única la clase de capa de símbolo — las básicas y predeterminadas son los tipos de capas de
símbolo `` SimpleMarker “”, `` SimpleLine “” y `` SimpleFill “”.
1 AnimatedMarker
2 EllipseMarker
3 FilledMarker
4 FontMarker
5 GeometryGenerator
6 MaskMarker
7 RasterMarker
8 SimpleMarker
9 SvgMarker
10 VectorField
La clase QgsSymbolLayerRegistry gestiona una base de datos de todos los tipos de capas de símbolos
disponibles.
Para acceder a los datos de la capa de símbolos, use su método properties() que devuelve un diccionario de
propiedades clave-valor que determina la apariencia. Cada tipo de capa de símbolo tiene un conjunto específico
de propiedades que utiliza. Además, existen los métodos genéricos color(), size(), angle() y width(),
con sus contrapartes setter. Por supuesto, el tamaño y el ángulo solo están disponibles para las capas de símbolo de
marcador y el ancho para las capas de símbolo de línea.
Imagine que le gustaría personalizar la forma en que se procesan los datos. Puede crear su propia clase de capa de
símbolo que dibujará las entidades exactamente como lo desee. Aquí hay un ejemplo de un marcador que dibuja
círculos rojos con un radio especificado
4 class FooSymbolLayer(QgsMarkerSymbolLayer):
5
11 def layerType(self):
12 return "FooMarker"
13
14 def properties(self):
15 return { "radius" : str([Link]) }
16
30 def clone(self):
31 return FooSymbolLayer([Link])
El layerType() el método determina el nombre de la capa de símbolo; tiene que ser único entre todas las capas
de símbolos. El método properties() es usada para la persistencia de sus atributos. El método clone() debe
devolver una copia de la capa de símbolo con todos los atributos exactamente iguales. Finalmente, existen métodos
de renderizado: startRender() se llama antes de renderizar la primera entidad, stopRender() cuando el
renderizado está terminado, y renderPoint() es llamado para hacer el renderizado. Las coordenadas de los
puntos ya están transformadas a las coordenadas de salida.
Para polilíneas y polígonos, la única diferencia estaría en el método de representación: que usaría
renderPolyline () que recibe una lista de líneas, mientras que :meth:`renderPolygon()
<[Link]> `recibe una lista de puntos en el anillo exterior como primer
parámetro y una lista de anillos interiores (o Ninguno) como segundo parámetro.
Por lo general, es conveniente agregar una GUI para configurar los atributos del tipo de capa de símbolo para permitir
a los usuarios personalizar la apariencia: en el caso de nuestro ejemplo anterior, podemos permitir que el usuario
establezca el radio del círculo. El siguiente código implementa dicho widget
3 class FooSymbolLayerWidget(QgsSymbolLayerWidget):
4 def __init__(self, parent=None):
5 QgsSymbolLayerWidget.__init__(self, parent)
6
7 [Link] = None
8
9 # setup a simple UI
10 [Link] = QLabel("Radius:")
11 [Link] = QDoubleSpinBox()
12 [Link] = QHBoxLayout()
13 [Link]([Link])
14 [Link]([Link])
15 [Link]([Link])
16 [Link]([Link], SIGNAL("valueChanged(double)"), \
17 [Link])
18
25 def symbolLayer(self):
26 return [Link]
27
Este widget se puede incrustar en el cuadro de diálogo de propiedades del símbolo. Cuando se selecciona el tipo de
capa de símbolo en el cuadro de diálogo de propiedades de símbolo, crea una instancia de la capa de símbolo y una
instancia del widget de capa de símbolo. Luego llama al método setSymbolLayer() para asignar la capa de
símbolo al widget. En ese método, el widget debería actualizar la interfaz de usuario para reflejar los atributos de la
capa de símbolo. El método symbolLayer() se usa para recuperar la capa de símbolo nuevamente mediante el
diálogo de propiedades para usarla para el símbolo.
En cada cambio de atributos, el widget debe emitir la señal changed() para permitir que el diálogo de propiedades
actualice la vista previa del símbolo.
Ahora solo nos falta el pegamento final: hacer que QGIS esté al tanto de estas nuevas clases. Esto se hace agregando
la capa de símbolo al registro. También es posible utilizar la capa de símbolo sin agregarla al registro, pero algunas
funciones no funcionarán: p. Ej. carga de archivos de proyecto con capas de símbolo personalizadas o incapacidad
para editar los atributos de la capa en la GUI.
Tendremos que crear metadatos para la capa de símbolo.
3 class FooSymbolLayerMetadata(QgsSymbolLayerAbstractMetadata):
4
5 def __init__(self):
6 super().__init__("FooMarker", "My new Foo marker", [Link])
7
12 fslmetadata = FooSymbolLayerMetadata()
[Link]().addSymbolLayerType(fslmetadata)
Debe pasar el tipo de capa (el mismo que devuelve la capa) y el tipo de símbolo (marcador / línea /
relleno) al constructor de la clase principal. El método createSymbolLayer() se encarga de crear una
instancia de la capa de símbolo con los atributos especificados en el diccionario props. Y esta el método
createSymbolLayerWidget() que devuelve el widget de configuración para este tipo de capa de símbolo.
El último pase es adicionar esta capa símbolo al registro — y estamos listos.
Puede ser útil crear una nueva implementación de renderizador si desea personalizar las reglas sobre cómo seleccionar
símbolos para renderizar características. Algunos casos de uso en los que desearía hacerlo: el símbolo se determina a
partir de una combinación de campos, el tamaño de los símbolos cambia según la escala actual, etc.
El siguiente código muestra un renderizador personalizado simple que crea dos símbolos de marcador y elige
aleatoriamente uno de ellos para cada objeto.
1 import random
2 from [Link] import QgsWkbTypes, QgsSymbol, QgsFeatureRenderer
3
5 class RandomRenderer(QgsFeatureRenderer):
6 def __init__(self, syms=None):
7 super().__init__("RandomRenderer")
8 [Link] = syms if syms else [
9 [Link]([Link]([Link])),
10 [Link]([Link]([Link]))
11 ]
12
El constructor de la clase padre QgsFeatureRenderer necesita un nombre de renderizador (que tiene que ser
único entre los renderizadores). El método symbolForFeature() es el que decide qué símbolo se utilizará para
una entidad en particular. startRender() y stopRender() se encargan de la inicialización/finalización de la
representación de símbolos. El método usedAttributes() puede devolver una lista de nombres de campo que el
renderizador espera que esté presente. Finalmente, el método clone() debería devolver una copia del renderizador.
Al igual que con las capas de símbolos, es posible adjuntar una GUI para la configuración del renderizador. Tiene
que derivarse de QgsRendererWidget. El siguiente código de muestra crea un botón que permite al usuario
establecer el primer símbolo
1 from [Link] import QgsRendererWidget, QgsColorButton
2
4 class RandomRendererWidget(QgsRendererWidget):
5 def __init__(self, layer, style, renderer):
6 super().__init__(layer, style)
7 if renderer is None or [Link]() != "RandomRenderer":
8 self.r = RandomRenderer()
9 else:
10 self.r = renderer
11 # setup UI
12 self.btn1 = QgsColorButton()
13 [Link]([Link][0].color())
14 [Link] = QVBoxLayout()
15 [Link](self.btn1)
16 [Link]([Link])
17 [Link](self.setColor1)
18
19 def setColor1(self):
20 color = [Link]()
21 if not [Link](): return
22 [Link][0].setColor(color)
23
24 def renderer(self):
25 return self.r
7 class RandomRendererMetadata(QgsRendererAbstractMetadata):
8
9 def __init__(self):
10 super().__init__("RandomRenderer", "Random renderer")
11
18 rrmetadata = RandomRendererMetadata()
[Link]().addRenderer(rrmetadata)
Del mismo modo que con las capas de símbolo, el constructor de metadatos abstracto espera el nombre del
renderizador, el nombre visible para los usuarios y, opcionalmente, el nombre del icono del renderizador. El
método createRenderer() pasa una instancia QDomElement que puede usarse para restaurar el estado del
renderizador desde el árbol DOM. El método createRendererWidget() crea el widget de configuración. No
tiene que estar presente o puede devolver Ninguno si el renderizador no viene con GUI.
Para asociar un icono con el renderizador, puede asignarlo en el constructor QgsRendererAbstractMetadata
como tercer argumento (opcional) — el constructor de la clase base en la función RandomRendererMetadata
__init__() se convierte en
QgsRendererAbstractMetadata.__init__(self,
"RandomRenderer",
"Random renderer",
QIcon(QPixmap("[Link]", "png")))
El icono también se puede asociar en cualquier momento posterior mediante el método setIcon() de la clase de
metadatos. El icono se puede cargar desde un archivo (como se muestra arriba) o se puede cargar desde un recurso
Qt (PyQt5 incluye el compilador .qrc para Pitón).
PENDIENTE:
• crear/modificar símbolos
• trabajandocon estilo (QgsStyle)
• trabajando con rampas de color (QgsColorRamp)
• explorar la capa de símbolo y los registros de renderizado
Manejo de Geometría
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
Los puntos, las cadenas de líneas y los polígonos que representan una característica espacial se conocen comúnmente
como geometrías. En QGIS están representados con la clase QgsGeometry.
A veces una geometría es realmente una colección simple (partes simples) geométricas. Tal geometría se llama
geometría de múltiples partes. Si contiene un tipo de geometría simple, lo llamamos un punto múltiple, lineas múltiples
o polígonos múltiples. Por ejemplo, un país consiste en múltiples islas que se pueden representar como un polígono
múltiple.
Las coordenadas de las geometrías pueden estar en cualquier sistema de referencia de coordenadas (SRC). Cuando
extrae características de una capa, las geometrías asociadas tendrán sus coordenadas en el SRC de la capa.
Descripción y especificaciones de todas las posibles geometrías de construcción y las relaciones están disponibles en
el OGC Simple Feature Access Standards para detalles avanzados.
51
PyQGIS 3.40 developer cookbook
1 gPnt = [Link](QgsPointXY(1,1))
2 print(gPnt)
3 gLine = [Link]([QgsPoint(1, 1), QgsPoint(2, 2)])
4 print(gLine)
5 gPolygon = [Link]([[QgsPointXY(1, 1),
6 QgsPointXY(2, 2), QgsPointXY(2, 1)]])
7 print(gPolygon)
Las coordenadas son dadas usando la clase QgsPoint o la clase QgsPointXY. La diferencia entre estas
clases es que soporten QgsPoint dimensione M y Z.
Una polilínea (cadena lineal) es representada por una lista de puntos.
Un polígono está representado por una lista de anillos lineales (es decir, cadenas de líneas cerradas). El primer
anillo es el anillo exterior (límite), los anillos subsiguientes opcionales son agujeros en el polígono. Tenga en
cuenta que, a diferencia de algunos programas, QGIS cerrará el anillo por usted, por lo que no es necesario
duplicar el primer punto como el último.
Las geometrías multi-parte van un nivel más allá: multi-punto es una lista de puntos, multi-linea es una lista de
polilíneas y multi-polígono es una lista de polígonos.
• desde well-known text (WKT)
1 g = QgsGeometry()
2 wkb = [Link]("010100000000000000000045400000000000001440")
3 [Link](wkb)
4
Primero, debe averiguar el tipo de geometría. El método wkbType() es el que se va a utilizar. Devuelve un valor
de la enumeración [Link].
1 print([Link]())
2 # output: 1
3 print([Link]())
4 # output: 2
5 print([Link]())
6 # output: 3
Como alternativa, se puede utilizar el método type() que devuelve un valor de la enumeración QgsWkbTypes.
GeometryType.
print([Link]())
# output: 1
Puede usar la función displayString() para obtener un tipo de geometría legible por humanos.
1 print([Link]([Link]()))
2 # output: 'Point'
3 print([Link]([Link]()))
4 # output: 'LineString'
5 print([Link]([Link]()))
6 # output: 'Polygon'
También hay una función de ayuda isMultipart() para saber si una geometría es multiparte o no.
Para extraer información de una geometría, existen funciones de acceso para cada tipo de vector. A continuación, se
muestra un ejemplo sobre cómo utilizar estos accesos:
1 print([Link]())
2 # output: <QgsPointXY: POINT(1 1)>
3 print([Link]())
4 # output: [<QgsPointXY: POINT(1 1)>, <QgsPointXY: POINT(2 2)>]
5 print([Link]())
6 # output: [[<QgsPointXY: POINT(1 1)>, <QgsPointXY: POINT(2 2)>, <QgsPointXY:␣
,→POINT(2 1)>, <QgsPointXY: POINT(1 1)>]]
Nota: Las tuplas (x, y) no son tuplas reales, son objetos QgsPoint, los valores son accesibles con los métodos x()
y y().
Point (0 0)
Point (1 1)
Point (2 2)
LineString (0 0, 10 10)
gc = QgsGeometryCollection()
[Link]('GeometryCollection( Point(1 2), Point(11 12), LineString(33 34, 44 45))
,→')
print(gc[1].asWkt())
9 print([Link]())
,→5072020.35880533326417208))
QGIS utiliza la biblioteca GEOS para operaciones de geometría avanzadas como predicados de geometría
(contains(), intersects(), …) y hacer operaciones (combine(), difference(), …). También puede
calcular propiedades geométricas de geometrías, como área (en el caso de polígonos) o longitudes (para polígonos y
líneas).
Veamos un ejemplo que combina iterar sobre las entidades en una capa determinada y realizar algunos cálculos
geométricos basados en sus geometrías. El siguiente código calculará e imprimirá el área y el perímetro de cada país
en la capa de países dentro de nuestro proyecto tutorial QGIS.
El siguiente código asume que layer es un obleto QgsVectorLayer que tiene el tipo de entidad Polígono.
4 # let's filter for countries that begin with Z, then get their features
5 query = '"name" LIKE \'Z%\''
6 features = [Link](QgsFeatureRequest().setFilterExpression(query))
7
8 # now loop through the features, perform geometry computation and print the results
9 for f in features:
10 geom = [Link]()
11 name = [Link]('NAME')
12 print(name)
13 print('Area: ', [Link]())
14 print('Perimeter: ', [Link]())
1 Zambia
2 Area: 62.82279065343119
3 Perimeter: 50.65232014052552
4 Zimbabwe
5 Area: 33.41113559136517
6 Perimeter: 26.608288555013935
Ahora ha calculado e impreso las áreas y perímetros de las geometrías. Sin embargo, puede notar rápidamente que
los valores son extraños. Esto se debe a que las áreas y los perímetros no tienen en cuenta el CRS cuando se calculan
con los métodos area() y length() desde la clase QgsGeometry. Para un cálculo de área y distancia más
potente, la clase QgsDistanceArea se puede utilizar, que puede realizar cálculos basados en elipsoides:
El siguiente código asume que layer es un obleto QgsVectorLayer que tiene el tipo de entidad Polígono.
1 d = QgsDistanceArea()
2 [Link]('WGS84')
3
4 layer = [Link]().mapLayersByName('countries')[0]
5
6 # let's filter for countries that begin with Z, then get their features
7 query = '"name" LIKE \'Z%\''
8 features = [Link](QgsFeatureRequest().setFilterExpression(query))
9
17 # let's calculate and print the area again, but this time in square kilometers
18 print("Area (km2):", [Link]([Link](geom), QgsUnitTypes.
,→AreaSquareKilometers))
1 Zambia
2 Perimeter (m): 5539361.250294601
3 Area (m2): 751989035032.9031
4 Area (km2): 751989.0350329031
5 Zimbabwe
6 Perimeter (m): 2865021.3325076113
7 Area (m2): 389267821381.6008
8 Area (km2): 389267.8213816008
1 d = QgsDistanceArea()
2 [Link]('WGS84')
3
Puede encontrar muchos ejemplos de algoritmos que se incluyen en QGIS y utilizan estos métodos para analizar y
transformar los datos vectoriales. Aquí hay algunos enlaces al código de algunos de ellos.
• Distancia y área usando QgsDistanceArea class: Distance matrix algorithm
• Lines to polygons algorithm
Soporte de Proyecciones
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
True
57
PyQGIS 3.40 developer cookbook
True
• cree un SRC no válido y luego use una de las funciones crear* para inicializarlo. En el siguiente ejemplo
usamos una cadena Proj para inicializar la proyección.
crs = QgsCoordinateReferenceSystem()
[Link]("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
print([Link]())
True
Es aconsejable comprobar si la creación (es decir, la búsqueda en la base de datos) del SRC se ha realizado
correctamente: isValid() debe devolver True.
Tenga en cuenta que para la inicialización de sistemas de referencia espacial, QGIS necesita buscar los valores
apropiados en su base de datos interna [Link]. Por lo tanto, en caso de que cree una aplicación independiente,
debe configurar las rutas correctamente con [Link](), de lo contrario, no podrá
encontrar la base de datos. Si está ejecutando los comandos desde la consola de QGIS Python o desarrollando un
complemento, no le importa: todo ya está configurado para usted.
Acceso a la información del sistema de referencia espacial:
1 crs = QgsCoordinateReferenceSystem("EPSG:4326")
2
Salida:
Puede realizar la transformación entre diferentes sistemas de referencia espacial utilizando la clase
QgsCoordinateTransform. La forma más fácil de usarlo es crear un SRC de origen y destino y construir una
instancia QgsCoordinateTransform con ellos y el proyecto actual. Luego simplemente llame repetidamente
transform() function para hacer la transformación. De forma predeterminada, realiza una transformación hacia
adelante, pero también es capaz de realizar una transformación inversa.
Salida:
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
El widget del lienzo del mapa es probablemente el widget más importante dentro de QGIS porque muestra el mapa
integrado de capas de mapas superpuestos y permite la interacción con el mapa y las capas. El lienzo muestra siempre
una parte del mapa definido por el alcance del lienzo actual. La interacción se realiza mediante el uso de herramientas
de mapa: hay herramientas para desplazamiento, zum, la identificación de las capas, de medida, para editar vectores
y otros. Al igual que en otros programas de gráficos, siempre hay una herramienta activa y el usuario puede cambiar
entre las herramientas disponibles.
El lienzo del mapa está implementado con la clase QgsMapCanvas en el módulo [Link] . La implementación
61
PyQGIS 3.40 developer cookbook
se basa en el marco Qt Graphics View. Este marco generalmente proporciona una superficie y una vista donde
se colocan elementos gráficos personalizados y el usuario puede interactuar con ellos. Asumiremos que está lo
suficientemente familiarizado con Qt para comprender los conceptos de escena, vista y elementos gráficos. Si no
es así, lea la descripción general del marco. <[Link]
Cada vez que el mapa se ha desplazado, ampliado / reducido (o alguna otra acción que desencadena una actualización),
el mapa se representa nuevamente dentro de la extensión actual. Las capas se representan en una imagen (utilizando la
clase QgsMapRendererJob) y esa imagen se muestra en el lienzo. La clase QgsMapCanvas También controla
la actualización del mapa representado. Además de este elemento que actúa como fondo, puede haber más elementos
de lienzo de mapas.
Los elementos típicos del lienzo del mapa son bandas elásticas (utilizadas para medir, editar vectores, etc.) o
marcadores de vértice. Los elementos del lienzo generalmente se usan para dar retroalimentación visual a las
herramientas de mapa, por ejemplo, al crear un nuevo polígono, la herramienta de mapa crea un elemento de lienzo
con banda elástica que muestra la forma actual del polígono. Todos los elementos del lienzo del mapa son subclases
de QgsMapCanvasItem que agrega más funcionalidad a los objetos básicos QGraphicsItem.
Para resumir, la arquitectura del lienzo de mapa consiste en tres conceptos:
• lienzo de mapa — para la visualización del mapa
• Los elementos de lienzo de mapa — los elementos adicionales que se pueden desplegar en un lienzo de mapa
• herramientas de mapa — para interactuar con el lienzo del mapa
Map Canvas es un widget como cualquier otro widget de Qt, por lo que usarlo es tan simple como crearlo y mostrarlo.
canvas = QgsMapCanvas()
[Link]()
Esto produce una ventana independiente con el lienzo de mapa. Puede también ser incrustado en un widget existente
o ventana. Al utilizar archivo ui y Qt Designer, coloque un QWidget sobre el formulario y promuévalo a una nueva
clase: establezca QgsMapCanvas como nombre de clase y [Link] como archivo de encabezado. La utilidad
pyuic5 se hará cargo de ella. Esta es una forma conveniente de incrustar el lienzo. La otra posibilidad es escribir
manualmente el código para construir el lienzo del mapa y otros widgets (como hijos de una ventana principal o
diálogo) y crea un diseño.
Por defecto, el lienzo de mapa tiene un fondo negro y no utiliza anti-aliasing. Para establecer el fondo blanco y habilitar
el anti-aliasing para suavisar la presentación
[Link]([Link])
[Link](True)
(En caso de que se esté preguntando, Qt viene del modulo [Link] y [Link] es uno de lo que predefine
las instancias QColor.)
Ahora es el momento de agregar algunas capas del mapa. Primero abriremos una capa y la agregaremos al proyecto
actual. Luego estableceremos la extensión del lienzo y la lista de capas para el lienzo.
2 if not [Link]():
3 print("Layer failed to load!")
4
Después de ejecutar estos comandos, el lienzo debe mostrar la capa que se ha cargado.
Para mostrar algunos datos adicionales en la parte superior del mapa en el lienzo, utilice los elementos del lienzo
de mapa. Es posible crear clases de elementos del lienzo personalizada (cubiertas más abajo), sin embargo, hay dos
clases de elementos de lienzo útiles para mayor comodidad QgsRubberBand para dibujar polilíneas o polígonos, y
QgsVertexMarker para dibujar puntos. Ambos trabajan con coordenadas de mapa, por lo que la figura se mueve/
se escala de forma automática cuando el lienzo está siendo desplazado o haciendo zum.
Para mostrar una polilínea:
Tenga en cuenta que los puntos de polígonos no es una lista simple: de hecho, es una lista de anillos que contienen
lista de anillos del polígono: el primer anillo es el borde exterior, anillos adicionales (opcional) corresponden a los
agujeros en el polígono.
Las bandas elásticas permiten algún tipo de personalizacion, es decir, para cambiar su color o ancho de línea
[Link](QColor(0, 0, 255))
[Link](3)
Los elementos del lienzo están vinculados a la escena del lienzo. Para ocultarlos temporalmente (y mostrarlos
nuevamente), use el combo hide() and show(). Para eliminar completamente el elemento, debe eliminarlo de la
escena del lienzo.
[Link]().removeItem(r)
(en C++ es posible simplemente eliminar el elemento, sin embargo en Python del r sería simplemente suprimir la
referencia y el objeto aún existirá ya que es propiedad del lienzo)
La banda de goma también se puede usar para dibujar puntos, pero la clase QgsVertexMarker Es más adecuada
para esto (QgsRubberBand solo dibujaría un rectángulo alrededor del punto deseado).
Puede usar el marcador de vértices así:
m = QgsVertexMarker(canvas)
[Link](QgsPointXY(10,40))
Esto dibujará una cruz roja en la posición [10,45]. Es posible personalizar el tipo de icono, tamaño, color y ancho del
lápiz.
Para ocultar temporalmente los marcadores de vértice y eliminarlos del lienzo, utilice los mismos métodos que para
las gomas elásticas.
El siguiente ejemplo construye una ventana que contiene un lienzo de mapa y herramientas de mapa básicas para
la panorámica y el zoom del mapa. Las acciones se crean para la activación de cada herramienta: la panorámica se
realiza con QgsMapToolPan, acercando/alejando con un par de instancias QgsMapToolZoom. Las acciones se
configuran como verificables y luego se asignan a las herramientas para permitir el manejo automático del estado
verificado / no verificado de las acciones: cuando una herramienta de mapa se activa, su acción se marca como
seleccionada y la acción de la herramienta de mapa anterior se deselecciona. Las herramientas de mapa se activan
usando setMapTool() method.
1 from [Link] import *
2 from [Link] import QAction, QMainWindow
3 from [Link] import Qt
4
5 class MyWnd(QMainWindow):
6 def __init__(self, layer):
7 QMainWindow.__init__(self)
8
9 [Link] = QgsMapCanvas()
10 [Link]([Link])
11
12 [Link]([Link]())
13 [Link]([layer])
14
15 [Link]([Link])
16
21 [Link](True)
22 [Link](True)
23 [Link](True)
24
25 [Link]([Link])
26 [Link]([Link])
27 [Link]([Link])
28
42 [Link]()
43
44 def zoomIn(self):
45 [Link]([Link])
46
47 def zoomOut(self):
(continúe en la próxima página)
50 def pan(self):
51 [Link]([Link])
Puede probar el código anterior en el editor de la consola de Python. Para invocar la ventana del lienzo, agregue las
siguientes líneas para crear una instancia de la clase ``MyWnd””. Representarán la capa seleccionada actualmente en
el lienzo recién creado
w = MyWnd([Link]())
[Link]()
Puedes usar la herramienta del mapa QgsMapToolIdentifyFeature para pedirle al usuario que seleccione
una entidad que se enviará a una función de devolución de llamada.
1 def callback(feature):
2 """Code called when the feature is selected by the user"""
3 print("You clicked on feature {}".format([Link]()))
4
5 canvas = [Link]()
6 feature_identifier = QgsMapToolIdentifyFeature(canvas)
7
11 # use the callback as a slot triggered when the user identifies a feature
12 feature_identifier.[Link](callback)
13
La interacción con el lienzo del mapa se puede hacer también por medio de entradas que usted puede hacer en su
menú contextual usando la señal contextMenuAboutToShow.
El siguiente código añade la acción Mi menú ► Mi Acción cerca de las entradas predeterminadas cuando hace pulsación
derecha sobre el lienzo del mapa.
8 [Link](populateContextMenu)
9 [Link]()
Puede escribir sus herramientas personalizadas, para implementar un comportamiento personalizado a las acciones
realizadas por los usuarios en el lienzo.
Las herramientas de mapa deben heredar de QgsMapTool, clase o cualquier clase derivada, y seleccionada como
herramientas activas en el lienzo utilizando el método setMapTool() como ya hemos visto.
Aquí esta un ejemplo de una herramienta de mapa para definir una extensión rectangular haciendo clic y arrastrando
en el lienzo. Cuando se define el rectángulo, imprime su limite de coordenadas en la consola. Utiliza los elementos
de la banda elástica descrita antes para mostrar el rectángulo seleccionado ya que se esta definiendo.
1 class RectangleMapTool(QgsMapToolEmitPoint):
2 def __init__(self, canvas):
3 [Link] = canvas
4 QgsMapToolEmitPoint.__init__(self, [Link])
5 [Link] = QgsRubberBand([Link], [Link])
6 [Link]([Link])
7 [Link](1)
8 [Link]()
9
10 def reset(self):
11 [Link] = [Link] = None
12 [Link] = False
13 [Link]([Link])
14
33 [Link] = [Link]([Link]())
34 [Link]([Link], [Link])
35
46 [Link](point1, False)
47 [Link](point2, False)
48 [Link](point3, False)
49 [Link](point4, True) # true to update canvas
50 [Link]()
(continúe en la próxima página)
52 def rectangle(self):
53 if [Link] is None or [Link] is None:
54 return None
55 elif ([Link].x() == [Link].x() or \
56 [Link].y() == [Link].y()):
57 return None
58
61 def deactivate(self):
62 [Link](self)
63 [Link]()
1 class CircleCanvasItem(QgsMapCanvasItem):
2 def __init__(self, canvas):
3 super().__init__(canvas)
4 [Link] = QgsPoint(0, 0)
5 [Link] = 100
6
10 def center(self):
11 return [Link]
12
16 def size(self):
17 return [Link]
18
19 def boundingRect(self):
20 return QRectF([Link].x() - [Link]/2,
21 [Link].y() - [Link]/2,
22 [Link].x() + [Link]/2,
23 [Link].y() + [Link]/2)
24
31
Consejo: Los fragmentos de código en esta página necesitan las siguientes importaciones:
1 import os
2
69
PyQGIS 3.40 developer cookbook
Por lo general, hay dos enfoques cuando los datos de entrada deben representarse como un mapa: hacerlo de
manera rápida usando QgsMapRendererJob o producir una salida más ajustada componiendo el mapa con la clase
QgsLayout.
3 vlayer = [Link]()
4 settings = QgsMapSettings()
5 [Link]([vlayer])
6 [Link](QColor(255, 255, 255))
7 [Link](QSize(800, 600))
8 [Link]([Link]())
9
10 render = QgsMapRendererParallelJob(settings)
11
12 def finished():
13 img = [Link]()
14 # save the image; e.g. [Link]("/Users/myuser/[Link]","png")
15 [Link](image_location, "png")
16
17 [Link](finished)
18
Si tiene más de una capa y tienen un SRC diferente, el simple ejemplo anterior probablemente no funcionará: para
obtener los valores correctos de los cálculos de extensión, debe establecer explícitamente el SRC de destino
layers = [[Link]()]
settings = QgsMapSettings()
[Link](layers)
[Link](layers[0].crs())
El diseño de impresión es una herramienta muy útil si desea realizar una salida más sofisticada que la simple
representación mostrada anteriormente. Es posible crear diseños de mapas complejos compuestos por vistas de mapas,
etiquetas, leyendas, tablas y otros elementos que suelen estar presentes en los mapas en papel. Los diseños pueden
exportarse a PDF, SVG, imágenes rasterizadas o imprimirse directamente en una impresora.
El diseño consta de varias clases. Todos pertenecen a la biblioteca principal. La aplicación QGIS tiene una GUI
conveniente para la ubicación de los elementos, aunque no está disponible en la biblioteca de la GUI. Si no está
familiarizado con Qt Graphics View framework, entonces le recomendamos que consulte la documentación ahora,
porque el diseño se basa en ella.
La clase central del diseño es la clase QgsLayout, que deriva de la clase de Qt QGraphicsScene . Creemos una
instancia de ello:
project = [Link]()
layout = QgsPrintLayout(project)
[Link]()
Esto inicializa el diseño con algunas configuraciones predeterminadas, específicamente agregando una página A4
vacía al diseño. Puede crear diseños sin llamar al método initializeDefaults(), pero deberá encargarse de
agregar páginas al diseño usted mismo.
El código anterior crea un diseño «temporal» que no es visible en la GUI. Puede ser útil [Link]. agregue rápidamente
algunos elementos y exporte sin modificar el proyecto en sí ni exponer estos cambios al usuario. Si desea que el diseño
se guarde/restaure junto con el proyecto y esté disponible en el administrador de diseño, agregue:
[Link]("MyLayout")
[Link]().addLayout(layout)
Ahora podemos agregar varios elementos (mapa, etiqueta, …) al diseño. Todos estos objetos están representados por
clases que heredan de la clase base QgsLayoutItem.
Aquí hay una descripción de algunos de los elementos de diseño principales que se pueden agregar a un diseño.
• mapa — Aquí creamos un mapa de un tamaño personalizado y renderizamos el lienzo del mapa actual.
1 map = QgsLayoutItemMap(layout)
2 # Set map item position and size (by default, it is a 0 width/0 height item␣
,→placed at 0,0)
3 [Link](QgsLayoutPoint(5,5, [Link]))
4 [Link](QgsLayoutSize(200,200, [Link]))
5 # Provide an extent to render
6 [Link]([Link]().extent())
7 [Link](map)
• etiqueta — permite mostrar etiquetas. Es posible modificar su letra, color, alineación y margen.
label = QgsLayoutItemLabel(layout)
[Link]("Hello world")
[Link]()
[Link](label)
• legend
legend = QgsLayoutItemLegend(layout)
[Link](map) # map is an instance of QgsLayoutItemMap
[Link](legend)
• barra de escala
1 item = QgsLayoutItemScaleBar(layout)
2 [Link]('Numeric') # optionally modify the style
3 [Link](map) # map is an instance of QgsLayoutItemMap
4 [Link]()
5 [Link](item)
1 polygon = QPolygonF()
2 [Link](QPointF(0.0, 0.0))
3 [Link](QPointF(100.0, 0.0))
4 [Link](QPointF(200.0, 100.0))
5 [Link](QPointF(100.0, 200.0))
6
10 props = {}
11 props["color"] = "green"
12 props["style"] = "solid"
13 props["style_border"] = "solid"
14 props["color_border"] = "black"
15 props["width_border"] = "10.0"
16 props["joinstyle"] = "miter"
17
18 symbol = [Link](props)
19 [Link](symbol)
Una vez que un elemento es añadido a la composiciónm puede ser movida y redimensionadas:
Un cuadro es dibujado alrededor de cada elemento por defecto. Puede borrarlo como sigue:
Además de crear los elementos de diseño a mano, QGIS tiene soporte para plantillas de diseño que son esencialmente
composiciones con todos sus elementos guardados en un archivo .qpt (con sintaxis XML).
Una vez que la composición está lista (los elementos de diseño se han creado y agregado a la composición), podemos
proceder a producir una salida rasterizada y/o vectorial.
Un diseño está formado por un conjunto de elementos interconectados y puede ocurrir que estas conexiones se
rompan durante las modificaciones (una leyenda conectada a un mapa eliminado, un elemento de imagen al que
le falta el archivo fuente,…) o puede que desee aplicar restricciones personalizadas a los elementos del diseño. La
QgsAbstractValidityCheck te ayuda a conseguirlo.
Una comprobación básica tiene este aspecto:
@[Link](type=[Link])
def my_layout_check(context, feedback):
results = ...
return results
Aquí hay una comprobación que lanza una advertencia cada vez que un elemento de mapa de diseño se establece en
la proyección mercator web:
1 @[Link](type=[Link])
2 def layout_map_crs_choice_check(context, feedback):
3 layout = [Link]
4 results = []
5 for i in [Link]():
6 if isinstance(i, QgsLayoutItemMap) and [Link]().authid() == 'EPSG:3857':
7 res = QgsValidityCheckResult()
8 [Link] = [Link]
9 [Link] = 'Map projection is misleading'
10 [Link] = 'The projection for the map item {} is set to <i>
,→Web Mercator (EPSG:3857)</i> which misrepresents areas and shapes. Consider␣
11 [Link](res)
12
13 return results
Y aquí hay un ejemplo más complejo, que lanza una advertencia si cualquier elemento de mapa de diseño se establece
en un SRC que sólo es válido fuera de la extensión mostrada en ese elemento de mapa:
1 @[Link](type=[Link])
2 def layout_map_crs_area_check(context, feedback):
3 layout = [Link]
4 results = []
5 for i in [Link]():
6 if isinstance(i, QgsLayoutItemMap):
7 bounds = [Link]().bounds()
8 ct = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:4326'),␣
,→[Link](), [Link]())
9 bounds_crs = [Link](bounds)
10
11 if not bounds_crs.contains([Link]()):
12 res = QgsValidityCheckResult()
13 [Link] = [Link]
14 [Link] = 'Map projection is incorrect'
15 [Link] = 'The projection for the map item {} is␣
,→set to \'{}\', which is not valid for the area displayed within the map.'.
,→format([Link](), [Link]().authid())
16 [Link](res)
17
18 return results
1 base_path = [Link]([Link]().homePath())
2 pdf_path = [Link](base_path, "[Link]")
3
4 exporter = QgsLayoutExporter(layout)
5 [Link](pdf_path, [Link]())
Si desea exportar todas las páginas de un diseño que tiene la opción de atlas configurada y habilitada, debe usar el
método atlas() en el exportador (QgsLayoutExporter) con pequeños ajustes. En el siguiente ejemplo, las
páginas se exportan a imágenes PNG:
Observe que las salidas se guardarán en la carpeta de ruta base, utilizando la expresión de nombre de archivo de salida
configurada en atlas.
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
QGIS tiene cierto soporte para analizar expresiones similares a SQL. Solo se admite un pequeño subconjunto de
sintaxis SQL. Las expresiones se pueden evaluar como predicados booleanos (devolviendo True o False) o como
funciones (devolviendo un valor escalar). Consulte vector_expressions en el Manual del usuario para obtener una lista
completa de las funciones disponibles.
Se le da apoyo a tres tipos:
• numero - números enteros y números con decimales, e.j. 123, 3.14
• cadena - se tiene que encerrar en comas individuales: 'hola mundo'
• columna de referencia - cuando se evalúa, la referencia se substituye con el valor actual del campo. Los nombres
no se escapan.
Los siguientes operadores están disponibles:
• operadores aritméticos: «+». «-», «/», ^
• paréntesis: para hacer cumplir la precedencia del operador: (1 + 1) * 3
• unario mas y menos: -12, +5
75
PyQGIS 3.40 developer cookbook
El siguiente ejemplo muestra cómo verificar si una expresión dada se puede analizar correctamente:
Las expresiones se pueden usar en diferentes contextos, por ejemplo, para filtrar entidades o para calcular nuevos
valores de campo. En cualquier caso, la expresión tiene que ser evaluada. Eso significa que su valor se calcula
realizando los pasos computacionales especificados, que pueden variar desde expresiones aritméticas simples hasta
expresiones agregadas.
Para evaluar una expresión sobre una entidad, se debe crear un objeto :clase:`QgsExpressionContext
<[Link]>` y pasarlo a la función de evaluación para permitir que la expresión acceda a
los valores de campo de la entidad.
El siguiente ejemplo muestra cómo crear una entidad con un campo llamado «Columna» y cómo agregar esta entidad
al contexto de expresión.
1 fields = QgsFields()
2 field = QgsField('Column')
3 [Link](field)
4 feature = QgsFeature()
5 [Link](fields)
6 [Link](0, 99)
7
8 exp = QgsExpression('"Column"')
9 context = QgsExpressionContext()
10 [Link](feature)
11 [Link](context)
12 # 99
El siguiente es un ejemplo más completo de cómo usar expresiones en el contexto de una capa vectorial, para calcular
nuevos valores de campo:
27 [Link]()
28 [Link]().addMapLayer(vl)
29
39 # [Link]() is a convenience
40 # function that adds the global, project, and layer scopes all at once.
41 # Alternatively, those scopes can also be added manually. In any case,
42 # it is important to always go from “most generic” to “most specific”
43 # scope, i.e. from global to project to layer
44 context = QgsExpressionContext()
45 [Link]([Link](vl))
46
47 with edit(vl):
48 for f in [Link]():
49 [Link](f)
50 f['Rev. per employee'] = [Link](context)
51 f['Sum'] = [Link](context)
52 f['Fun'] = [Link](context)
53 [Link](f)
54
55 print(f['Sum'])
876.5
El siguiente ejemplo se puede utilizar para filtra capas y regresar cualquier característica que empata con el predicado.
1 layer = QgsVectorLayer("Point?field=Test:integer",
2 "addfeat", "memory")
3
4 [Link]()
5
6 for i in range(10):
7 feature = QgsFeature()
8 [Link]([i])
9 assert([Link](feature))
10 [Link]()
11
15 matches = 0
(continúe en la próxima página)
19 print(matches)
Los errores relacionados con la expresión pueden ocurrir durante el análisis o la evaluación de expresiones:
5 value = [Link]()
6 if [Link]():
7 raise ValueError([Link]())
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
Muchas veces es útil para un complemento guardar algunas variables para que el usuario no tenga que introducir o
seleccionar de nuevo la próxima vez que el complemento se ejecute.
Estas variables se pueden guardar y recuperar con ayuda de Qt y QGIS API. Para cada variable, se debe escoger
una clave que será utilizada para acceder a la variable — para el color favorito del usuario podría utilizarse la clave
«favourite_color» o cualquier otra cadena que tenga sentido. Es recomendable dar un poco de estructura al nombrar
las claves.
Podemos diferenciar entre varios tipos de configuraciones:
• global settings — están vinculados al usuario en una máquina en particular. QGIS almacena muchas
configuraciones globales, por ejemplo, el tamaño de la ventana principal o la tolerancia de ajuste
predeterminada. La configuración se maneja usando la clase QgsSettings, por ejemplo, a través de
setValue() y :meth:`value() < [Link]>`métodos.
Aquí puede ver un ejemmplo de como se usan estos métodos.
1 def store():
2 s = QgsSettings()
3 [Link]("myplugin/mytext", "hello world")
4 [Link]("myplugin/myint", 10)
5 [Link]("myplugin/myreal", 3.14)
6
7 def read():
8 s = QgsSettings()
9 mytext = [Link]("myplugin/mytext", "default text")
10 myint = [Link]("myplugin/myint", 123)
11 myreal = [Link]("myplugin/myreal", 2.71)
(continúe en la próxima página)
81
PyQGIS 3.40 developer cookbook
El segundo parámetro del método value() es opcional y especifica el valor predeterminado que se devuelve
si no hay un valor anterior establecido para el nombre de configuración pasado.
Para conocer un método para preconfigurar los valores predeterminados de las configuraciones globales a través
del archivo qgis_global_settings.ini, consulte deploying_organization para obtener más detalles.
• project settings — varían entre diferentes proyectos y, por lo tanto, están conectados con un archivo de
proyecto. El color de fondo del lienzo del mapa o el sistema de referencia de coordenadas de destino (CRS) son
ejemplos: el fondo blanco y WGS84 pueden ser adecuados para un proyecto, mientras que el fondo amarillo y
la proyección UTM son mejores para otro.
A continuación se muestra un ejemplo de uso.
1 proj = [Link]()
2
3 # store values
4 [Link]("myplugin", "mytext", "hello world")
5 [Link]("myplugin", "myint", 10)
6 [Link]("myplugin", "mydouble", 0.01)
7 [Link]("myplugin", "mybool", True)
8
9 # read values (returns a tuple with the value, and a status boolean
10 # which communicates whether the value retrieved could be converted to
11 # its type, in these cases a string, an integer, a double and a boolean
12 # respectively)
13
Como puede ver, el método writeEntry() es usado para muchos tipos de datos (entero, cadena, lista),
pero existen varios métodos para volver a leer el valor de ajuste, y se debe seleccionar el correspondiente para
cada tipo de datos.
• map layer settings — esta configuración está relacionada con una instancia particular de una capa de mapa
con un proyecto. No están conectados con la fuente de datos subyacente de una capa, por lo que si crea dos
instancias de capa de mapa de un archivo de forma, no compartirán la configuración. La configuración se
almacena dentro del archivo del proyecto, por lo que si el usuario abre el proyecto nuevamente, la configuración
relacionada con la capa volverá a estar allí. El valor para una configuración dada se recupera usando el método
customProperty(), y se puede establecer usando el método setCustomProperty() uno.
1 vlayer = QgsVectorLayer()
2 # save a value
3 [Link]("mytext", "hello world")
4
83
PyQGIS 3.40 developer cookbook
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
1 from [Link] import (
2 QgsMessageLog,
3 QgsGeometry,
4 )
5
Esta sección muestra algunos métodos y elementos que deberían utilizarse para comunicarse con el usuario, con el
objetivo de mantener la consistencia en la Interfaz del Usuario.
Utilizar las bandejas de mensajes puede ser una mala idea desde el punto de vista de la experiencia de un usuario.
Para mostrar una pequeña línea de información o mensajes de advertencia/error, la barrar de mensajes de QGIS suele
ser una mejor opción.
Utilizar la referencia a la interfaz objeto de QGIS, puede mostrar un mensaje en la barra de mensajes con el siguiente
código
from [Link] import Qgis
[Link]().pushMessage("Error", "I'm sorry Dave, I'm afraid I can't do that
,→", level=[Link])
85
PyQGIS 3.40 developer cookbook
Los ejemplos anteriores muestran una barra de error, pero el parámetro level se puede usar para crear mensajes
de advertencia o mensajes de información, utilizando la enumeración [Link]. Puede usar hasta 4
niveles diferentes:
0. Información
1. Advertencia
2. Critica
3. Éxito
Se puede añadir complementos a la barra de mensajes, como por ejemplo un botón para mostrar más información
1 def showError():
2 pass
3
Incluso puedes utilizar una barra de mensajes en tu propio cuadro de diálogo para no tener que mostrar la bandeja de
mensajes o si no tiene sentido mostrarla en la pantalla principal de QGIS.
1 class MyDialog(QDialog):
2 def __init__(self):
3 QDialog.__init__(self)
4 [Link] = QgsMessageBar()
5 [Link]( [Link], [Link] )
6 [Link](QGridLayout())
7 [Link]().setContentsMargins(0, 0, 0, 0)
8 [Link] = QDialogButtonBox([Link])
9 [Link]([Link])
10 [Link]().addWidget([Link], 0, 0, 2, 1)
11 [Link]().addWidget([Link], 0, 0, 1, 1)
12 def run(self):
13 [Link]("Hello", "World", level=[Link])
14
15 myDlg = MyDialog()
16 [Link]()
Las barras de progreso también pueden ponerse en la barra de Mensajes de QGIS, ya que, como hemos visto, admite
complementos. Este es un ejemplo que puedes probar en la consola.
1 import time
2 from [Link] import QProgressBar
3 from [Link] import *
4 progressMessageBar = [Link]().createMessage("Doing something boring...")
5 progress = QProgressBar()
6 [Link](10)
7 [Link]([Link]|[Link])
8 [Link]().addWidget(progress)
9 [Link]().pushWidget(progressMessageBar, [Link])
10
11 for i in range(10):
12 [Link](1)
13 [Link](i + 1)
14
15 [Link]().clearWidgets()
Además, puede usar el constructor en la barra de estado para comunicar progreso, como en el siguiente ejemplo:
1 vlayer = [Link]()
2
3 count = [Link]()
4 features = [Link]()
5
12 [Link]().showMessage("Processed {} %".format(int(percent)))
13
14 [Link]().clearMessage()
13.3 Registro
Hay tres tipos diferentes de registro disponible en QGIS para registrar y guardar toda la información sobre la ejecución
de su código. Cada uno tiene una ubicación de salida específica. Por favor considere el uso de la forma correcta de
registro para su propósito:
• QgsMessageLog es para que los mensajes comuniquen problemas al usuario. La salida del QgsMessageLog
es mostrada en el Panel de Mensajes de Registro.
• El python construido en el módilo registro es para depuración en el nivel de la API Python QGIS (PyQGIS).
Es recomendado para desarrolladores de script Python que necesitan depurar su código python, e.g. ids o
geometría de objeto espacial
• QgsLogger es para mensajes para depuración / desarrolladores internos QGIS (i.e. usted sospecha que algo
es gatillado por algún código dañado). Los mensajes sólo están visibles con versiones desarrollador de QGIS.
Ejemplos para los diferentes tipos de registro son mostrados en las siguientes secciones abajo.
Advertencia: El uso de la declaración print Python no es segura en ningún código que sea multihilos y
ralentiza extremadamente el algoritmo. Esto incluye funciones de expresión, representadores, capas de
símbolo y algoritmos Procesos (entre otros). En estos casos usted siempre debería usar en vez el módulo python
registro o clases seguras de hilo (QgsLogger o QgsMessageLog).
13.3.1 QgsMessageLog
13.3. Registro 89
PyQGIS 3.40 developer cookbook
1 import logging
2 formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
3 logfilename=r'c:\temp\[Link]'
4 [Link](filename=logfilename, level=[Link], format=formatter)
5 [Link]("This logging info text goes into the file")
6 [Link]("This logging debug text goes into the file as well")
El método basicConfig configura la definición básica del registro. En el código de arriba el nombre de archivo, nivel
de registro y el formato son definidos. El nombre de archivo se refiere a donde escribir el archivo de registro, el nivel
de registro define qué niveles imprimir y el formato define el formato en el que cada mensaje es impreso.
2020-10-08 [Link],998 - root - INFO - This logging text goes into the file
2020-10-08 [Link],998 - root - DEBUG - This logging debug text goes into the␣
,→file as well
Si quiere borrar el archivo de registro cada vez que ejecuta su script usted puede hacer algo como:
if [Link](logfilename):
with open(logfilename, 'w') as file:
pass
Mayores recursos sobre cómo usar la instalación de registro python están disponibles en:
• [Link]
• [Link]
• [Link]
Advertencia: Por favor tome nota que sin registrar a un archivo al definir el nombre de archivo, el registro podría
darse en multihilos lo que ralentiza fuertemente la salida.
Infraestructura de autenticación
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
91
PyQGIS 3.40 developer cookbook
14.1 Introducción
La referencia de Usuario de la infraestructura de Autenticación puede ser leída en el Manual del Usuario en el párrafo
authentication_overview.
En este capítulo se describen las mejores prácticas para usar el sistema de autenticación desde una perspectiva de
desarrollador.
El sistema de autenticación es ampliamente utilizado en QGIS Desktop por los proveedores de datos siempre que se
requieren credenciales para acceder a un recurso en particular, por ejemplo, cuando una capa establece una conexión
a una base de datos de Postgres.
También hay algunos widgets en la biblioteca de interfaz gráfica de usuario de QGIS que los desarrolladores de
complementos pueden usar para integrar fácilmente la infraestructura de autenticación en su código:
• QgsAuthConfigEditor
• QgsAuthConfigSelect
• QgsAuthSettingsWidget
Se puede leer una buena referencia de código desde la infraestructura de autenticación tests code.
Advertencia: Debido a las restricciones de seguridad que se tuvieron en cuenta durante el diseño de la
infraestructura de autenticación, solo un subconjunto seleccionado de los métodos internos están expuestos a
Python.
14.2 Glosario
Aquí hay algunas definiciones de los objetos más comunes tratados en este capítulo.
Contraseña maestra
Contraseña para permitir el acceso y descifrar las credenciales almacenadas en la base de datos de autenticación
de QGIS
BBDD de Autenticación
Un Master Password encriptado sqlite db [Link] donde Authentication Configuration son
almacenados. [Link]. usuario/contraseña, certificados personales y claves, Autoridades de certificación
Autenticación BD
Authentication Database
Configuración de Autenticación
Un conjunto de datos de autenticación según Authentication Method. [Link]. El método de Autenticación básica
almacena el par de usuario/contraseña.
Configuración de autenticación
Authentication Configuration
Método de autenticación
Un método específico utilizado para autenticarse. Cada método tiene su propio protocolo utilizado para obtener
el nivel autenticado. Cada método se implementa como una biblioteca compartida cargada dinámicamente
durante el inicio de la infraestructura de autenticación de QGIS.
El QgsAuthManager singleton es el punto de entrada para usar las credenciales almacenadas en el QGIS encriptado
BBDD Autenticación, es decir, el archivo [Link] en la carpeta activa perfil de usuario.
Esta clase se encarga de la interacción del usuario: solicitando establecer una contraseña maestra o utilizándola de
forma transparente para acceder a la información almacenada cifrada.
El siguiente fragmento ofrece un ejemplo para establecer una contraseña maestra para abrir el acceso a la configuración
de autenticación. Los comentarios de código son importantes para comprender el fragmento.
1 authMgr = [Link]()
2
authcfg = 'fm1s770'
esa cadena se genera automáticamente al crear una entrada utilizando la API o GUI de QGIS, pero podría ser útil
establecerla manualmente en un valor conocido en caso de que la configuración deba compartirse (con diferentes
credenciales) entre varios usuarios dentro de una organización.
QgsAuthMethodConfig es la clase base para cualquier Método de autenticación. Cualquier método de
autenticación establece un mapa hash de configuración donde se almacenará la información de autenticación. A
continuación, un fragmento útil para almacenar las credenciales de ruta PKI para un usuario hipotético de Alice:
1 authMgr = [Link]()
2 # set alice PKI data
3 config = QgsAuthMethodConfig()
4 [Link]("alice")
(continúe en la próxima página)
Authentication Method las bibliotecas se cargan dinámicamente durante el inicio del administrador de autenticación.
Los métodos de autenticación disponibles son:
1. Basic Autenticación de usuario y contraseña
2. EsriToken Autenticación basada en token ESRI
3. Identity-Cert Autenticación del certificado de identidad
4. OAuth2 autenticación OAuth2
5. PKI-Paths Autenticación de rutas PKI
6. PKI-PKCS#12 PKI PKCS#12 Autenticación
Populate Authorities
1 authMgr = [Link]()
2 # add authorities
3 cacerts = [Link]( "/path/to/ca_chains.pem" )
4 assert cacerts is not None
5 # store CA
6 [Link](cacerts)
7 # and rebuild CA caches
8 [Link]()
9 [Link]()
Una clase de conveniencia para empaquetar paquetes PKI compuestos en cadenas SslCert, SslKey y CA es la clase
QgsPkiBundle. A continuación, un fragmento para protegerse con contraseña:
Podemos borrar una entrada de Authentication Database usando su identificador authcfg con el siguiente
fragmento:
authMgr = [Link]()
[Link]( "authCfg_Id_to_remove" )
Nota: Tenga en cuenta que no todos los proveedores de datos de QGIS están integrados con la infraestructura de
autenticación. Cada método de autenticación, derivado de la clase base QgsAuthMethod y soporta un conjunto
diferente de Proveedores. Por ejemplo el método certIdentity() soporta la siguiente lista de proveedores:
authM = [Link]()
print([Link]("Identity-Cert").supportedDataProviders())
Salida de muestra:
Por ejemplo, para acceder a un servicio WMS usando credenciales almacenadas identificadas con authcfg =
'fm1s770', solo tenemos que usar el authcfg en la URL de la fuente de datos como en el siguiente fragmento:
1 authCfg = 'fm1s770'
2 quri = QgsDataSourceUri()
3 [Link]("layers", 'usa:states')
4 [Link]("styles", '')
5 [Link]("format", 'image/png')
6 [Link]("crs", 'EPSG:4326')
7 [Link]("dpiMode", '7')
8 [Link]("featureCount", '10')
9 [Link]("authcfg", authCfg) # <---- here my authCfg url parameter
10 [Link]("contextualWMSLegend", '0')
11 [Link]("url", '[Link]
12 rlayer = QgsRasterLayer(str([Link](), "utf-8"), 'states', 'wms')
En mayúsculas, el proveedor wms se encargará de expandir el parámetro URI authcfg con credencial justo antes
de configurar la conexión HTTP.
Advertencia: El desarrollador tendría que dejar la expansión ʻauthcfg` a QgsAuthManager, de esta manera
se asegurará de que la expansión no se haga demasiado pronto.
Por lo general, una cadena URI, construida usando la clase QgsDataSourceURI , se utiliza para configurar una
fuente de datos de la siguiente manera:
authCfg = 'fm1s770'
quri = QgsDataSourceUri("my WMS uri here")
[Link]("authcfg", authCfg)
rlayer = QgsRasterLayer( [Link](False), 'states', 'wms')
Nota: El parámetro False es importante para evitar la expansión completa de URI del id authcfg presente en
el URI.
Otro ejemplo se puede leer directamente en las pruebas de QGIS en sentido ascendente como en
test_authmanager_pki_ows o test_authmanager_pki_postgres.
Muchos complementos de terceros están utilizando httplib2 u otras bibliotecas de red de Python para administrar las
conexiones HTTP en lugar de integrarse con QgsNetworkAccessManager y su integración relacionada con la
infraestructura de autenticación.
Para facilitar esta integración se ha creado una función auxiliar de Python llamada NetworkAccessManager.
Su código se puede encontrar aquí.
Esta clase auxiliar se puede utilizar como en el siguiente fragmento:
2 try:
3 response, content = [Link]( "my_rest_url" )
4 except My_FailedRequestError, e:
5 # Handle exception
6 pass
En este párrafo se enumeran las IGU disponibles útiles para integrar la infraestructura de autenticación en interfaces
personalizadas.
Si es necesario seleccionar un Authentication Configuration del conjunto almacenado en la BBDD Autenticación está
disponible en la clase IGU QgsAuthConfigSelect.
El ejemplo anterior está tomado de la fuente QGIS code. El segundo parámetro del constructor de GUI se refiere
al tipo de proveedor de datos. El parámetro se utiliza para restringir el Método de autenticación compatible con el
proveedor especificado.
La GUI completa utilizada para administrar credenciales, autoridades y para acceder a las utilidades de autenticación
es administrada por la clase QgsAuthEditorWidgets.
Una GUI utilizada para administrar solo las autoridades es administrada por la clase
QgsAuthAuthoritiesEditor.
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
1 from [Link] import (
2 Qgis,
3 QgsApplication,
4 QgsMessageLog,
5 QgsProcessingAlgRunnerTask,
6 QgsProcessingContext,
7 QgsProcessingFeedback,
8 QgsProject,
9 QgsTask,
10 QgsTaskManager,
11 )
15.1 Introducción
El procesamiento en segundo plano utilizando subprocesos es una forma de mantener una interfaz de usuario receptiva
cuando se está realizando un procesamiento pesado. Las tareas se pueden utilizar para realizar subprocesos en QGIS.
Una tarea (QgsTask) es un contenedor para el código que se realizará en segundo plano, y el administrador de tareas
(QgsTaskManager) se usa para controlas la ejecución de las tareas. Estas clases simplifican el procesamiento en
segundo plano en QGIS al proporcionar mecanismos de señalización, informes de progreso y acceso al estado de los
procesos en segundo plano. Las tareas se pueden agrupar mediante subtareas.
El administrador de tareas global (encontrado con [Link]()) es usado
normalmente. Esto significa que sus tareas pueden no ser las únicas tareas controladas por el administrador de tareas.
Hay varias vías para crear una tarea QGIS:
• Crea tu propia tarea extendiendo QgsTask
class SpecialisedTask(QgsTask):
pass
99
PyQGIS 3.40 developer cookbook
1 def heavyFunction():
2 # Some CPU intensive processing ...
3 pass
4
5 def workdone():
6 # ... do something useful with the results
7 pass
8
1 params = dict()
2 context = QgsProcessingContext()
3 [Link]([Link]())
4 feedback = QgsProcessingFeedback()
5
6 buffer_alg = [Link]().processingRegistry().algorithmById(
,→'native:buffer')
Advertencia: Cualquier tarea en segundo plano (independientemente de cómo se cree) NUNCA debe usar ningún
QObject que viva en el hilo principal, como acceder a QgsVectorLayer, QgsProject o realizar cualquier operación
basada en GUI como crear nuevos widgets o interactuar con widgets existentes. Solo se debe acceder o modificar
los widgets de Qt desde el hilo principal. Los datos que se utilizan en una tarea se deben copiar antes de iniciar la
tarea. Intentar utilizarlos desde subprocesos en segundo plano provocará bloqueos.
Además asegúrese siempre de que context y feedback viven al menos tanto tiempo como las tareas que
los utilizan. QGIS se bloqueará si, al finalizar una tarea, QgsTaskManager falla al acceder al context y feedback
contra los que se programó la tarea.
Nota: Es un patrón común llamar setProject() poco después de llamar a QgsProcessingContext. Esto
permite que la tarea, así como su función de devolución de llamada, utilicen la mayor parte de la configuración de
todo el proyecto. Esto es especialmente valioso cuando se trabaja con capas espaciales en la función callback.
Las dependencias entre tareas se pueden describir utilizando la función addSubTask() de QgsTask. Cuando
se establece una dependencia, el administrador de tareas determinará automáticamente cómo se ejecutarán estas
dependencias. Siempre que sea posible, las dependencias se ejecutarán en paralelo para satisfacerlas lo más rápido
posible. Si se cancela una tarea de la que depende otra tarea, la tarea dependiente también se cancelará. Las
dependencias circulares pueden hacer posibles los interbloqueos, así que tenga cuidado.
Si una tarea depende de que haya una capa disponible, esto se puede indicar usando la función
setDependentLayers() de QgsTask. Si una capa de la que depende una tarea no está disponible, la tarea se
cancelará.
Una vez que se ha creado la tarea, se puede programar su ejecución utilizando la función addTask() del
administrador de tareas. Agregar una tarea al administrador transfiere automáticamente la propiedad de esa tarea al
administrador, y el administrador limpiará y eliminará las tareas después de que se hayan ejecutado. La programación
de las tareas está influenciada por la prioridad de la tarea, que se establece en addTask().
El estado de las tareas puede ser monitorizado usando señales y funciones QgsTask y QgsTaskManager.
15.2 Ejemplos
En este ejemplo RandomIntegerSumTask se extiende QgsTask y generará 100 enteros aleatorios entre 0 y 500
durante un período de tiempo específico. Si el número aleatorio es 42, la tarea se cancela y se genera una excepción.
Se generan y agregan varias instancias de RandomIntegerSumTask (con subtareas) al administrador de tareas,
lo que demuestra dos tipos de dependencias.
1 import random
2 from time import sleep
3
8 MESSAGE_CATEGORY = 'RandomIntegerSumTask'
9
10 class RandomIntegerSumTask(QgsTask):
11 """This shows how to subclass QgsTask"""
12
20 def run(self):
21 """Here you implement your heavy lifting.
22 Should periodically test for isCanceled() to gracefully
23 abort.
24 This method MUST return True or False.
25 Raising exceptions will crash QGIS, so we handle them
26 internally and raise them in [Link]
27 """
28 [Link]('Started task "{}"'.format(
29 [Link]()),
30 MESSAGE_CATEGORY, [Link])
31 wait_time = [Link] / 100
32 for i in range(100):
33 sleep(wait_time)
34 # use setProgress to report progress
35 [Link](i)
36 arandominteger = [Link](0, 500)
37 [Link] += arandominteger
38 [Link] += 1
39 # check isCanceled() to handle cancellation
40 if [Link]():
41 return False
42 # simulate exceptions to show how to abort task
43 if arandominteger == 42:
44 # DO NOT raise Exception('bad value!')
45 # this would crash QGIS
46 [Link] = Exception('bad value!')
47 return False
48 return True
49
85 def cancel(self):
86 [Link](
87 'RandomTask "{name}" was canceled'.format(
88 name=[Link]()),
89 MESSAGE_CATEGORY, [Link])
90 super().cancel()
91
92
109 [Link]().addTask(longtask)
110 [Link]().addTask(shorttask)
111 [Link]().addTask(minitask)
Cree una tarea desde una función (doSomething en este ejemplo). El primer parámetro de la función contendrá
el QgsTask para la función. Un importante parámetro(llamado) es on_finished, que especifica una función
que se llamará cuando la tarea se haya completado. La función doSomething en este ejemplo tiene un parámetro
adicional llamado wait_time.
1 import random
2 from time import sleep
3
4 MESSAGE_CATEGORY = 'TaskFromFunction'
5
36 def stopped(task):
37 [Link](
38 'Task "{name}" was canceled'.format(
39 name=[Link]()),
(continúe en la próxima página)
Crear una tarea que use el algoritmo qgis:randompointsinextent para generar 50000 puntos aleatorios dentro de una
extensión específica. El resultado se agrega al proyecto de manera segura.
7 MESSAGE_CATEGORY = 'AlgRunnerTask'
8
23 alg = [Link]().algorithmById(
24 'qgis:randompointsinextent')
25 # `context` and `feedback` need to
26 # live for as least as long as `task`,
27 # otherwise the program will crash.
28 # Initializing them globally is a sure way
29 # of avoiding this unfortunate situation.
30 context = QgsProcessingContext()
31 feedback = QgsProcessingFeedback()
32 params = {
33 'EXTENT': '0.0,10.0,40,50 [EPSG:4326]',
34 'MIN_DISTANCE': 0.0,
35 'POINTS_NUMBER': 50000,
36 'TARGET_CRS': 'EPSG:4326',
37 'OUTPUT': 'memory:My random points'
38 }
39 task = QgsProcessingAlgRunnerTask(alg, params, context, feedback)
40 [Link](partial(task_finished, context))
41 [Link]().addTask(task)
Antes de empezar a escribir un nuevo complemento, eche un vistazo al Repositorio oficial de complementos de Python.
El código fuente de los complementos existentes puede ayudarle a aprender más sobre programación. También puedes
encontrar que ya existe un complemento similar y puede ser capaz de extenderlo o al menos basarte en él para
desarrollar el tuyo propio.
107
PyQGIS 3.40 developer cookbook
Para empezar con un nuevo complemento, necesitamos configurar los archivos necesarios del complemento.
Existen dos recursos de plantillas de complementos que pueden ayudarle a empezar:
• Para fines educativos o siempre que se desee un enfoque minimalista, la plantilla minimal plugin template
proporciona los archivos básicos (esqueleto) necesarios para crear un complemento válido de QGIS Python.
• Para una plantilla de complemento más completa, el Plugin Builder puede crear plantillas para múltiples tipos
de complementos diferentes, incluyendo características como localización (traducción) y pruebas.
Un directorio de complementos típico incluye los siguientes archivos:
• [Link] - requerido - Contiene información general, versión, nombre y algunos otros metadatos
utilizados por el sitio web de complementos y la infraestructura de complementos.
• __init__.py - requerido - El punto de inicio del complemento. Tiene que tener el método
classFactory() y puede tener cualquier otro código de inicialización.
• [Link] - código núcleo - El código principal de trabajo del complemento. Contiene toda la
información sobre las acciones del complemento y el código principal.
• [Link] - para complementos con IGU personalizada - La IGU creada por Qt Designer.
• [Link] - GUI compilado - La traducción del [Link] descrito anteriormente a Python.
• [Link] - opcional - Un documento .xml creado por Qt Designer. Contiene rutas relativas a los
recursos utilizados en los formularios GUI.
• [Link] - recursos compilados, opcional - La traducción del archivo .qrc descrito anteriormente a
Python.
• LICENSE - required if plugin is to be published or updated in the QGIS Plugins Directory, otherwise optional.
File should be a plain text file with no file extension in the filename.
Advertencia: Si planea subir el complemento al Repositorio oficial de complementos de Python debe comprobar
que su complemento sigue algunas reglas adicionales, requeridas para el complemento Validación.
La siguiente sección muestra qué contenido debe añadirse en cada uno de los archivos introducidos anteriormente.
[Link]
En primer lugar, el Gestor de Complementos necesita recuperar cierta información básica sobre el complemento,
como su nombre, descripción, etc. Esta información se almacena en [Link].
Nombre Necesario
Notas
de
metadatos
Nombre Verdadero
una cadena corta que contiene el nombre del complemento
qgisMinimumVersion
Verdadero
notación con puntos de la versión mínima de QGIS
qgisMaximumVersion
Falso notación con puntos de la versión máxima de QGIS
description Verdaderotexto breve que describe el complemento, no se permite HTML
about Verdadero
texto más largo que describe el complemento en detalles, no se permite HTML
version Verdadero
cadena corta con la notación punteada de la versión
author Verdadero
nombre del autor
email Verdadero
correo electrónico del autor, que solo se muestra en el sitio web para los usuarios que han
iniciado sesión, pero que es visible en el Administrador de complementos después de instalar
el complemento
changelog Falso cadena, puede ser de varias líneas, no se permite HTML
experimental Falso bandera booleana, True o False - True si esta versión es experimental
deprecated Falso bandera booleana, True o False, se aplica a todo el complemento y no solo a la versión
cargada
etiquetas Falso lista separada por comas, los espacios son permitidos dentro de etiquetas individuales
homepage Falso una URL válida que apunta a la página de inicio de su complemento
repository Verdadero
una URL válida al repositorio de código fuente
tracker Falso Una URL válida a los tickets y reportes de errores
icon Falso un nombre de archivo o una ruta relativa (relativa a la carpeta base del paquete comprimido
del complemento) de una imagen compatible con la web (PNG, JPEG)
category Falso una de las siguientes opciones: Raster, Vector, Base de datos, Malla y Web.
plugin_dependencies
Falso Lista separada por comas de otros complementos a instalar, utiliza los nombres de los
complementos procedentes del campo de nombre de sus metadatos
server Falso bandera booleana, True o False, determina si el complemento tiene una interfaz de
servidor
hasProcessingProvider
Falso bandera booleana, True o False, determina si el complemento proporciona algoritmos
de procesamiento
De forma predeterminada, los complementos se colocan en el menú Complementos (veremos en la siguiente sección
cómo añadir una entrada de menú para tu complemento) pero también pueden colocarse en los menús Raster, Vector,
Base de datos, Malla y Web.
Existe una entrada de metadatos de «categoría» correspondiente para especificar eso, por lo que el complemento se
puede clasificar en consecuencia. Esta entrada de metadatos se utiliza como sugerencia para los usuarios y les dice
dónde (en qué menú) se puede encontrar el complemento. Los valores permitidos para «categoría» son: Vectorial,
Ráster, Base de datos o Web. Por ejemplo, si su complemento estará disponible en el menú Ráster, agréguelo a
[Link]
category=Raster
Nota: Si qgisMaximumVersion está vacío, se establecerá automáticamente en la versión principal más .99 cuando se
cargue en el Repositorio oficial de complementos de Python.
[general]
name=HelloWorld
email=me@[Link]
author=Just Me
qgisMinimumVersion=3.0
description=This is an example plugin for greeting the world.
(continúe en la próxima página)
; Tags are in comma separated value format, spaces are allowed within the
; tag name.
; Tags should be in English language. Please also check for existing tags and
; synonyms before creating a new one.
tags=wkt,raster,hello world
; deprecated flag (applies to the whole plugin and not only to the uploaded␣
,→version)
deprecated=False
__init__.py
Este archivo es requerido por el sistema de importación de Python. Además, QGIS requiere que este archivo contenga
una función classFactory(), que se llama cuando el complemento se carga en QGIS. Recibe una referencia a
la instancia de: class: QgisInterface <[Link]> y debe devolver un objeto de la clase de su complemento
desde [Link] — en nuestro caso se llama TestPlugin (ver más abajo). Así es como debería verse
__init __. Py
def classFactory(iface):
from .mainPlugin import TestPlugin
return TestPlugin(iface)
[Link]
Aquí es donde ocurre la magia y así es como se ve la magia: (por ejemplo [Link])
class TestPlugin:
def initGui(self):
# create action that will start plugin configuration
[Link] = QAction(QIcon("testplug:[Link]"),
"Test plugin",
[Link]())
[Link]("testAction")
[Link]("Configuration for test plugin")
[Link]("This is status tip")
[Link]([Link])
def unload(self):
# remove the plugin menu item and icon
[Link]("&Test plugins", [Link])
[Link]([Link])
def run(self):
# create and show a configuration dialog or something similar
print("TestPlugin: run called!")
Las únicas funciones de complemento que deben existir en el archivo fuente del complemento principal (por ejemplo
[Link]) son:
• __init__ que da acceso a la interfaz QGIS
• initGui() llamado cuando se carga el complemento
• unload() llamado cuando se descarga el complemento
En el ejemplo anterior, se usó addPluginToMenu(). Esto agregará la acción de menú correspondiente al menú
Complementos. Existen métodos alternativos para agregar la acción a un menú diferente. Aquí hay una lista de esos
métodos:
• addPluginToRasterMenu()
• addPluginToVectorMenu()
• addPluginToDatabaseMenu()
• addPluginToWebMenu()
Todos tienen la misma sintaxis que el método addPluginToMenu().
Se recomienda agregar su menú de complementos a uno de esos métodos predefinidos para mantener la coherencia
en la forma en que se organizan las entradas de los complementos. Sin embargo, puede agregar su grupo de menú
personalizado directamente a la barra de menú, como lo demuestra el siguiente ejemplo:
def initGui(self):
[Link] = QMenu([Link]())
[Link]("testMenu")
[Link]("MyMenu")
[Link] = QAction(QIcon("testplug:[Link]"),
"Test plugin",
[Link]())
[Link]("testAction")
[Link]("Configuration for test plugin")
[Link]("This is status tip")
[Link]([Link])
[Link]([Link])
menuBar = [Link]().menuBar()
[Link]([Link]().menuAction(),
[Link])
def unload(self):
[Link]()
No olvide establecer QAction y QMenu objectName con un nombre específico para su complemento para que
pueda personalizarse.
Aunque las acciones de ayuda y acerca de también se pueden añadir a su menú personalizado, un lugar conveniente
para hacerlas disponibles es en el menú principal de QGIS Ayuda ► Complementos. Esto se hace usando el método
pluginHelpMenu().
def initGui(self):
self.help_action = QAction(
QIcon("testplug:[Link]"),
[Link]("Test Plugin..."),
[Link]()
)
# Add the action to the Help menu
[Link]().addAction(self.help_action)
self.help_action.[Link](self.show_help)
@staticmethod
def show_help():
""" Open the online help. """
[Link](QUrl('[Link]
def unload(self):
[Link]().removeAction(self.help_action)
del self.help_action
Cuando trabaje en un complemento real, es aconsejable escribir el complemento en otro directorio (de trabajo) y crear
un archivo MAKE que generará UI + archivos de recursos e instalará el complemento en su instalación de QGIS.
La documentación del complemento se puede escribir como archivos de ayuda HTML. El módulo [Link]
proporciona una función, showPluginHelp() que abrirá el navegador de archivos de ayuda, de la misma manera
que otras ayudas de QGIS.
La función showPluginHelp() busca archivos de ayuda en el mismo directorio que el módulo de llamada.
Buscará, a su vez, index-ll_cc.html, [Link], [Link], index-en_us.html `y
:file:`[Link], mostrando el que encuentre primero. Aquí ll_cc es la configuración regional de QGIS.
Esto permite que se incluyan múltiples traducciones de la documentación con el complemento.
La función showPluginHelp() también puede tomar parámetros packageName, que identifica un complemento
específico para el que se mostrará la ayuda, nombre de archivo, que puede reemplazar» índice «en los nombres de
los archivos que se buscan, y sección, que es el nombre de una etiqueta de anclaje html en el documento en el que se
colocará el navegador.
Con unos pocos pasos, puede configurar el entorno para la localización del complemento de modo que, según la
configuración regional de su computadora, el complemento se cargue en diferentes idiomas.
Requisitos de Software
The easiest way to create and manage all the translation files is to install Qt Linguist. In a Debian-based GNU/Linux
environment you can install it typing:
Archivos y directorio
Cuando cree el complemento, encontrará la carpeta i18n dentro del directorio principal del complemento.
Todos los archivos de traducción deben estar dentro de este directorio.
archivo .pro
Primero debe crear un archivo .pro, que es un archivo proyecto que puede ser administrado por Qt Linguist.
En este archivo .pro debe especificar todos los archivos y formularios que desea traducir. Este archivo se utiliza para
configurar los archivos de localización y las variables. Un posible archivo de proyecto, que coincide con la estructura
de nuestro complemento de ejemplo:
FORMS = ../[Link]
SOURCES = ../your_plugin.py
TRANSLATIONS = your_plugin_it.ts
Su complemento puede seguir una estructura más compleja y puede estar distribuido en varios archivos. Si este es el
caso, tenga en cuenta que pylupdate5, el programa que usamos para leer el archivo .pro y actualizar la cadena
traducible, no expande los caracteres comodín, por lo que debe colocar cada archivo explícitamente en el archivo
.pro. Su archivo de proyecto podría verse así:
Además, el archivo your_plugin.py es el archivo que llama a todos los menús y submenús de su complemento
en la barra de herramientas de QGIS y desea traducirlos todos.
Finalmente, con la variable TRANSLATIONS puede especificar los idiomas de traducción que desee.
archivo .ts
Una vez que haya creado el .pro, estará listo para generar los archivos .ts para el(los) idioma(s) de su complemento.
Abra una terminal, vaya al directorio your_plugin/i18n y escriba:
pylupdate5 your_plugin.pro
archivo .qm
Cuando termine de traducir su complemento (si algunas cadenas no se completan, se utilizará el idioma de origen
para esas cadenas), debe crear el archivo .qm (el archivo .ts compilado que se utilizará por QGIS).
Simplemente abra un cd de terminal en el directorio your_plugin/i18n y escriba:
lrelease your_plugin.ts
Alternativamente, puede usar el archivo MAKE para extraer mensajes del código Python y los cuadros de diálogo
Qt, si creó su complemento con Plugin Builder. Al comienzo del Makefile hay una variable LOCALES:
LOCALES = en
Agregue la abreviatura del idioma a esta variable, por ejemplo, para el idioma húngaro:
LOCALES = en hu
Ahora puede generar o actualizar el archivo [Link] (y el [Link] también) desde las fuentes mediante:
make transup
Después de esto, ha actualizado el archivo .ts para todos los idiomas configurados en la variable LOCALES. Utilice
Qt Linguist para traducir los mensajes del programa. Al finalizar la traducción, el transcompile puede crear los
archivos .qm:
make transcompile
Carga el complemento
Para ver la traducción de su complemento, abra QGIS, cambie el idioma (Configuración -> Opciones -> General) y
reinicie QGIS.
Debería ver su complemento en el idioma correcto.
Advertencia: Si cambia algo en su complemento (nuevas IU, nuevo menú, etc.), debe generar nuevamente la
versión de actualización de los archivos .ts y .qm, así que vuelva a ejecutar el comando de arriba.
QGIS aloja cientos de complementos en el repositorio de complementos. ¡Considere compartir el suyo! Ampliará las
posibilidades de QGIS y la gente podrá aprender de su código. Todos los complementos alojados se pueden encontrar
e instalar desde QGIS con el Administrador de complementos.
La información y los requisitos están aquí: [Link].
Recargador de Complemento
Durante el desarrollo de su complemento, con frecuencia deberá volver a cargarlo en QGIS para realizar pruebas.
Esto es muy fácil con el complemento Recargador de complementos. Puedes encontrarlo con el Administrador de
Complementos.
qgis-plugin-ci provides a command line interface to perform automated packaging and deployment for QGIS plugins
on your computer, or using continuous integration like GitHub workflows or Gitlab-CI as well as Transifex for
translation.
Permite liberar, traducir, publicar o generar un archivo XML de repositorio de complementos a través de CLI o en
acciones CI.
Acceder a complementos
Puede acceder a todas las clases de complementos instalados desde QGIS utilizando Python, que puede ser útil para
fines de depuración.
Registro de Mensajes
Archivo de Recursos
Algunos complementos utilizan archivos de recursos, por ejemplo [Link] que definen recursos para la
interfaz gráfica de usuario, como iconos:
<RCC>
<qresource prefix="/plugins/testplug" >
<file>[Link]</file>
</qresource>
</RCC>
Es bueno usar un prefijo que no colisione con otros complementos o partes de QGIS, de lo contrario, podría obtener
recursos que no deseaba. Ahora solo necesita generar un archivo Python que contendrá los recursos. Se hace con el
comando pyrcc5:
Nota: En entornos Windows, intentar ejecutar pyrcc5 desde el símbolo del sistema o Powershell probablemente
resultará en el error» Windows no puede acceder al dispositivo, ruta o archivo especificado […] «. La solución más
fácil es probablemente utilizar OSGeo4W Shell, pero si se siente cómodo modificando la variable de entorno PATH
o especificando la ruta al ejecutable de forma explícita, debería poder encontrarla en <Your QGIS Install
Directory>\bin\[Link].
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
Esta sección cuenta con fragmentos de código para facilitar el desarrollo de complementos.
[Link](self.key_action)
def key_action_triggered(self):
[Link]([Link](),"Ok", "You pressed Ctrl+I")
También es posible permitir a los usuarios personalizar los atajos de teclado para las acciones proporcionadas. Esto
se hace añadiendo:
Debido a que son bien conocidos y transmiten un mensaje claro a los usuarios, es posible que a veces desee reutilizar
los iconos de QGIS en su plugin en lugar de dibujar y establecer uno nuevo. Utilice el método getThemeIcon().
Por ejemplo, para reutilizar el icono [Link] disponible en el repositorio de código de QGIS:
iconPath() es otro método para llamar a los iconos de QGIS. Encuentre ejemplos de llamadas a iconos temáticos
en Imágenes incrustadas de QGIS - Cheatsheet.
Puede agregar una pestaña de opciones de complementos personalizados a Configuración -> Opciones. Esto es
preferible a agregar una entrada de menú principal específica para las opciones de su complemento, ya que mantiene
todas las configuraciones de la aplicación QGIS y las configuraciones del complemento en un solo lugar que es fácil
de descubrir y navegar por los usuarios.
El siguiente fragmento solo agregará una nueva pestaña en blanco para la configuración del complemento, lista para
que la complete con todas las opciones y configuraciones específicas de su complemento. Puede dividir las siguientes
clases en diferentes archivos. En este ejemplo, estamos agregando dos clases al archivo principal [Link].
1 class MyPluginOptionsFactory(QgsOptionsWidgetFactory):
2
3 def __init__(self):
4 super().__init__()
5
6 def icon(self):
7 return QIcon('icons/my_plugin_icon.svg')
8
12
13 class ConfigOptionsPage(QgsOptionsPageWidget):
14
5 class MyPlugin:
6 """QGIS Plugin Implementation."""
7
19
20 def initGui(self):
21 self.options_factory = MyPluginOptionsFactory()
22 self.options_factory.setTitle([Link]('My Plugin'))
23 [Link](self.options_factory)
24
25 def unload(self):
26 [Link](self.options_factory)
Además de los elementos habituales de simbología de capas que se muestran al lado o debajo de la entrada de la
capa en el panel Capas, puede añadir sus propios widgets, permitiendo un acceso rápido a algunas acciones que se
utilizan a menudo con una capa (configuración de filtrado, selección, estilo, actualización de una capa con un widget
de botón, creación de un deslizador de tiempo basado en la capa o simplemente mostrar información adicional de la
capa en una etiqueta, o …). Estos llamados Widgets incrustados en el árbol de capas están disponibles a través de
la pestaña Legend de las propiedades de cada capa.
El siguiente fragmento de código crea un desplegable en la leyenda que muestra los estilos de capa disponibles para
la capa, permitiendo cambiar rápidamente entre los diferentes estilos de capa.
1 class LayerStyleComboBox(QComboBox):
2 def __init__(self, layer):
3 QComboBox.__init__(self)
4 [Link] = layer
5 for style_name in [Link]().styles():
6 [Link](style_name)
7
8 idx = [Link]([Link]().currentStyle())
9 if idx != -1:
10 [Link](idx)
11
12 [Link](self.on_current_changed)
13
17 class LayerStyleWidgetProvider(QgsLayerTreeEmbeddedWidgetProvider):
18 def __init__(self):
19 QgsLayerTreeEmbeddedWidgetProvider.__init__(self)
20
21 def id(self):
22 return "style"
23
24 def name(self):
25 return "Layer style chooser"
26
33 provider = LayerStyleWidgetProvider()
34 [Link]().addProvider(provider)
A continuación, desde la pestaña de propiedades Leyenda de una capa determinada, arrastre el Selector de
estilo de capa de Widgets disponibles a Widgets utilizados para habilitar el widget en el árbol de capas. Los
widgets incrustados SIEMPRE se muestran en la parte superior de sus subelementos de nodo de capa asociados.
Si quiere utilizar los widgets desde, por ejemplo, un complemento, puede añadirlos así:
1 layer = [Link]()
2 counter = int([Link]("embeddedWidgets/count", 0))
3 [Link]("embeddedWidgets/count", counter+1)
4 [Link]("embeddedWidgets/{}/id".format(counter), "style")
5 view = [Link]()
6 [Link]().refreshLayerLegend([Link]())
7 [Link]().setExpanded(True)
Aunque cada programador tiene su editor de texto/IDE preferido, aquí hay algunas recomendaciones para configurar
IDE populares para escribir y depurar complementos de QGIS Python.
Algunos complementos son convenientes al escribir complementos de Python. Desde Complementos ► Administrar
e instalar complementos…, instala:
• Plugin reloader: Esto le permitirá recargar un complemento y realizar nuevos cambios sin reiniciar QGIS.
• First Aid: Esto agregará una consola de Python y un depurador local para inspeccionar las variables cuando se
genere una excepción desde un complemento.
Advertencia: A pesar de nuestros constantes esfuerzos, es posible que la información más allá de esta línea no
esté actualizada para QGIS 3.
On Linux, Todo lo que normalmente se debe hacer es agregar las ubicaciones de la biblioteca QGIS a la variable de
entorno PYTHONPATH del usuario. En la mayoría de las distribuciones, esto se puede hacer editando ~/.bashrc
or ~/.bash-profile con la siguiente línea (probado en OpenSUSE Tumbleweed):
export PYTHONPATH="$PYTHONPATH:/usr/share/qgis/python/plugins:/usr/share/qgis/
,→python"
Guarde el archivo e implemente la configuración del entorno mediante el siguiente comando de shell:
source ~/.bashrc
On Windows, debe asegurarse de tener la misma configuración de entorno y utilizar las mismas bibliotecas e
intérprete que QGIS. La forma más rápida de hacerlo es modificar el archivo por lotes de inicio de QGIS.
Si utilizó el instalador de OSGeo4W, puede encontrarlo en la carpeta bin de su instalación de OSGeo4W. Busca
algo como C:\OSGeo4W\bin\[Link].
5. Ahora, cuando haga doble clic en este archivo por lotes, se iniciará Pyscripter, con la ruta correcta.
Más popular que Pyscripter, Eclipse es una opción común entre los desarrolladores. En la siguiente sección,
explicaremos cómo configurarlo para desarrollar y probar complementos.
Instalación
call "C:\OSGeo4W\bin\o4w_env.bat"
set PATH=%PATH%;C:\path\to\your\qgis_core.dll\parent\folder
start /B C:\path\to\your\[Link]
Configurando Eclipse
1. En Eclipse, cree un nuevo proyecto. Puede seleccionar * Proyecto general * y vincular sus fuentes reales más
adelante, por lo que realmente no importa dónde coloque este proyecto.
Configurar el depurador
Una cosa muy interesante que puede utilizar ahora es la consola de depuración. Asegúrese de que la ejecución esté
detenida en un punto de interrupción antes de continuar.
1. Abra la vista de la consola (Ventana ► Mostrar vista). Mostrará la consola Debug Server que no es muy
interesante. Pero hay un botón Abrir consola que le permite cambiar a una consola PyDev Debug más
interesante.
2. Haga clic en la flecha junto al: guilabel: botón «Abrir consola» y seleccione * Consola PyDev *. Se abre una
ventana para preguntarle qué consola desea iniciar.
3. Elija * PyDev Debug Console *. En caso de que esté atenuado y le indique que inicie el depurador y seleccione
el marco válido, asegúrese de que tiene el depurador remoto adjunto y se encuentra actualmente en un punto
de interrupción.
Ahora tiene una consola interactiva que le permite probar cualquier comando desde el contexto actual. Puedes
manipular variables o hacer llamadas a API o lo que quieras.
Truco: Un poco molesto es que cada vez que ingresa un comando, la consola vuelve al servidor de depuración. Para
detener este comportamiento, puede hacer clic en el botón * Fijar consola * cuando esté en la página del servidor de
depuración y debe recordar esta decisión al menos para la sesión de depuración actual.
Una característica muy útil es que Eclipse conozca realmente la API de QGIS. Esto le permite verificar su código en
busca de errores tipográficos. Pero no solo esto, también permite que Eclipse lo ayude con el autocompletado desde
las importaciones hasta las llamadas a la API.
Para hacer esto, Eclipse analiza los archivos de la biblioteca de QGIS y obtiene toda la información. Lo único que
tienes que hacer es decirle a Eclipse dónde encontrar las bibliotecas.
1. Click Ventana ► Preferencias ► PyDev ► Intérprete ► Python.
Verá su intérprete de Python configurado en la parte superior de la ventana (en este momento python2.7 para
QGIS) y algunas pestañas en la parte inferior. Las pestañas más interesantes para nosotros son * Bibliotecas *
y * Forced Builtins *.
3. Introduce qgis
4. y presione Entrar. Le mostrará qué módulo QGIS utiliza y su ruta.
5. Quite el /qgis/__init__.pyc final de esta ruta y obtendrá la ruta que está buscando.
4. También debe agregar su carpeta de complementos aquí (está en python/complementos debajo de la
carpeta user profile).
5. Luego salte a la pestaña * Forced Builtins *, haga clic en * New … * e ingrese `` qgis “”. Esto hará que Eclipse
analice la API de QGIS. Probablemente también desee que Eclipse conozca la API de PyQt. Por lo tanto,
también agregue PyQt como incorporado forzado. Eso probablemente ya debería estar presente en la pestaña
de bibliotecas.
6. Click en Aceptar y ya estas listo.
Nota: Cada vez que cambia la API de QGIS (por ejemplo, si está compilando el maestro QGIS y el archivo SIP
cambió), debe volver a esta página y simplemente hacer clic en Aplicar. Esto permitirá que Eclipse vuelva a analizar
todas las bibliotecas.
PyCharm es un IDE para Python desarrollado por JetBrains. Hay una versión gratuita llamada Community Edition y
una de pago llamada Professional. Puede descargar PyCharm en el sitio web: [Link]
download
Suponemos que ha compilado QGIS en Ubuntu con el directorio de compilación proporcionado ~/dev/qgis/
build/master. No es obligatorio tener un QGIS autocompilado, pero solo esto ha sido probado. Los caminos
deben adaptarse.
1. En PyCharm, en su: guilabel: Propiedades del proyecto, Intérprete del proyecto, vamos a crear un entorno virtual
Python llamado `` QGIS``.
2. Haga clic en el engranaje pequeño y luego Añadir.
3. Selecciona Virtualenv environment.
4. Seleccione una ubicación genérica para todos sus proyectos de Python, como ~/dev/qgis/venv porque
usaremos este intérprete de Python para todos nuestros complementos.
5. Elija un intérprete base de Python 3 disponible en su sistema y marque las siguientes dos opciones Inherit global
site-packages y Poner a disposición de todos los proyectos.
1. Reinicie PyCharm y podrá comenzar a usar este nuevo entorno virtual de Python para todos sus complementos.
PyCharm conocerá la API de QGIS y también la API de PyQt si usa Qt proporcionado por QGIS como from
[Link] import QDir. El autocompletado debería funcionar y PyCharm puede inspeccionar su
código.
En la versión profesional de PyCharm, la depuración remota funciona bien. Para la edición Community, la depuración
remota no está disponible. Solo puede tener acceso a un depurador local, lo que significa que el código debe ejecutarse
dentro de PyCharm (como script o unittest), no en QGIS. Para el código Python que se ejecuta en QGIS, puede usar
el complemento First Aid mencionado anteriormente.
Si no usa un IDE como Eclipse o PyCharm, puede depurar usando PDB, siguiendo estos pasos.
1. Primero agregue este código en el lugar donde le gustaría depurar
$ ./Qgis
En macOS haga:
$ /Applications/[Link]/Contents/MacOS/Qgis
Una vez que su complemento esté listo y crea que el complemento podría ser útil para algunas personas, no dude
en cargarlo en Repositorio oficial de complementos de Python. En esa página también puede encontrar pautas de
empaquetado sobre cómo preparar el complemento para que funcione bien con el instalador del complemento. O en
caso de que desee configurar su propio repositorio de complementos, cree un archivo XML simple que enumere los
complementos y sus metadatos.
Preste especial atención a las siguientes sugerencias:
• no incluya el archivo generado (ui_*.py, resources_rc.py, archivos de ayuda generados …) y cosas inútiles (por
ejemplo, .gitignore) en el repositorio
• agregue el complemento al menú apropiado (Vector, Raster, Web, Database)
• cuando sea apropiado (complementos que realizan análisis), considere agregar el complemento como un
subplugin del marco de procesamiento: esto permitirá a los usuarios ejecutarlo en lotes, integrarlo en flujos
de trabajo más complejos y lo liberará de la carga de diseñar una interfaz
• incluya al menos documentación mínima y, si es útil para probar y comprender, datos de muestra.
Permisos
Gestión de confianza
Los miembros del personal pueden otorgar confianza a los creadores de complementos seleccionados que configuran
el permiso plugins.can_approve a través de la aplicación frontal.
La vista de detalles del complemento ofrece enlaces directos para otorgar confianza al creador del complemento o los
propietarios del complemento.
Validación
Los metadatos del complemento se importan y validan automáticamente desde el paquete comprimido cuando se
carga el complemento.
Aquí hay algunas reglas de validación que debe conocer cuando desee cargar un complemento en el repositorio oficial:
1. el nombre de la carpeta principal que contiene su complemento debe contener solo caracteres ASCII (A-Z y
a-z), dígitos y los caracteres de subrayado (_) y menos (-), además no puede comenzar con un dígito
2. [Link] es requerido
3. todos los metadatos requeridos enumerados en tabla de metadatos deben estar presentes
4. el campo de metadatos versión debe ser único
5. debe incluirse un archivo de licencia, guardado como LICENSE sin extensión (es decir, no [Link]
por ejemplo)
Estructura de complementos
Siguiendo las reglas de validación, el paquete comprimido (.zip) de tu complemento debe tener una estructura
específica para ser validado como un complemento funcional. Como el complemento se descomprimirá dentro de la
carpeta de complementos del usuario, debe tener su propio directorio dentro del archivo .zip para no interferir con
otros complementos. Los archivos obligatorios son: [Link], __init__.py y LICENSE. Pero estaría
bien tener un README y por supuesto un icono para representar el complemento. A continuación se muestra un
ejemplo de cómo podría ser un [Link].
[Link]
pluginfolder/
|-- i18n
| |-- translation_file_de.ts
|-- img
| |-- [Link]
| |-- [Link]
|-- __init__.py
|-- LICENSE
|-- Makefile
|-- [Link]
|-- more_code.py
|-- main_code.py
|-- README
|-- ui_Qt_user_interface_file.ui
Es posible crear complementos en el lenguaje de programación Python. En comparación con los complementos
clásicos escritos en C++, estos deberían ser más fáciles de escribir, comprender, mantener y distribuir debido a la
naturaleza dinámica del lenguaje Python.
Los complementos de Python se enumeran junto con los complementos de C++ en el administrador de complementos
de QGIS. Se buscan en ~/(UserProfile)/python/plugins and these paths:
• UNIX/Mac: (qgis_prefix)/share/qgis/python/plugins
• Windows: (qgis_prefix)/python/plugins
Para definiciones de ~ y (UserProfile) vea core_and_external_plugins.
Nota: Al configurar QGIS_PLUGINPATH en una ruta de directorio existente, puede agregar esta ruta a la lista de
rutas en las que se buscan complementos.
Dependiendo del tipo de complemento que vaya a desarrollar, podría ser una mejor opción agregar su funcionalidad
como un algoritmo de procesamiento (o un conjunto de ellos). Eso proporcionaría una mejor integración dentro de
QGIS, funcionalidad adicional (ya que se puede ejecutar en los componentes de Processing, como el modelador o la
interfaz de procesamiento por lotes), y un tiempo de desarrollo más rápido (ya que Processing tomará una gran parte
del trabajo).
Para distribuir esos algoritmos, debe crear un nuevo complemento que los agregue a Caja de Herramientas de
Procesos. El complemento debe contener un proveedor de algoritmos, que debe registrarse cuando se crea una
instancia del complemento.
Para crear un complemento desde cero que contenga un proveedor de algoritmos, puede seguir estos pasos utilizando
el Generador de complementos:
1. Instala el complemento Plugin Builder
2. Crea un nuevo complemento, usando el Plugin Builder. En el cuadro de diálogo del Plugin Builder, selecciona
«Processing provider».
3. El complemento creado contiene un proveedor con un solo algoritmo. Tanto el archivo del proveedor como
el archivo del algoritmo están completamente comentados y contienen información sobre cómo modificar el
proveedor y agregar algoritmos adicionales. Consúltelos para obtener más información.
hasProcessingProvider=yes
2. En el archivo Python donde tu complemento está instalado con el método initGui, necesitas adaptar algunas
líneas como esta:
131
PyQGIS 3.40 developer cookbook
4 class YourPluginName:
5
6 def __init__(self):
7 [Link] = None
8
9 def initProcessing(self):
10 [Link] = Provider()
11 [Link]().addProvider([Link])
12
13 def initGui(self):
14 [Link]()
15
16 def unload(self):
17 [Link]().removeProvider([Link])
7 class Provider(QgsProcessingProvider):
8
11 def loadAlgorithms(self):
12 """ Load each algorithm into the current provider. """
13 [Link](ExampleProcessingAlgorithm())
14 # add additional algorithms here
15 # [Link](MyOtherAlgorithm())
16
1 └── your_plugin_root_folder
2 ├── __init__.py
3 ├── LICENSE
4 ├── [Link]
5 └── processing_provider
6 ├── example_processing_algorithm.py
7 ├── __init__.py
8 └── [Link]
1. Ahora puede volver a cargar su complemento en QGIS y debería ver su script de ejemplo en la caja de
herramientas de procesamiento y el modelador.
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
Si su complemento utiliza sus propios métodos para representar una capa de mapa, escribir su propio tipo de capa
basándose en QgsPluginLayer podría ser la mejor manera de implementarlo.
1 class WatermarkLayerRenderer(QgsMapLayerRenderer):
2
6 def render(self):
7 image = QImage("/usr/share/icons/hicolor/128x128/apps/[Link]")
8 painter = [Link]().painter()
9 [Link]()
10 [Link](10, 10, image)
11 [Link]()
(continúe en la próxima página)
135
PyQGIS 3.40 developer cookbook
14 class WatermarkPluginLayer(QgsPluginLayer):
15
16 LAYER_TYPE="watermark"
17
18 def __init__(self):
19 super().__init__(WatermarkPluginLayer.LAYER_TYPE, "Watermark plugin layer")
20 [Link](True)
21
28 # Methods for reading and writing specific information to the project file can
29 # also be added:
30
La capa de complemento se puede agregar al proyecto y al lienzo como cualquier otra capa de mapa:
plugin_layer = WatermarkPluginLayer()
[Link]().addMapLayer(plugin_layer)
Al cargar un proyecto que contiene dicha capa, se necesita una clase de fábrica:
1 class WatermarkPluginLayerType(QgsPluginLayerType):
2
3 def __init__(self):
4 super().__init__(WatermarkPluginLayer.LAYER_TYPE)
5
6 def createLayer(self):
7 return WatermarkPluginLayer()
8
9 # You can also add GUI code for displaying custom information
10 # in the layer properties
11 def showLayerProperties(self, layer):
12 pass
13
14
19 assert [Link]().addPluginLayerType(plt)
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
137
PyQGIS 3.40 developer cookbook
Lo primero que hay que hacer — es preparar la entrada de datos, que es convertir una capa vectorial en un gráfico.
Todas las acciones adicionales utilizarán esta gráfica, no la capa.
Como fuente podemos utilizar una capa vectorial de polilínea. Los nodos de las polilíneas se convierten en vértices
del gráfico, y los segmentos de la polilínea son bordes de gráfico. Si varios nodos tienen la misma coordenada entonces
ellos tienen el mimso vértice gráfico. Por lo que dos líneas que tienen un nodo en común se conectaran entre si.
Además durante la creación del gráfico se puede «arreglar» («atar») a la capa vectorial de entrada cualquier número
de puntos adicionales. Para cada punto adicional se encontrará una coincidencia — el vértice gráfico más cercano o
el borde gráfico más cercano. En el último caso el borde será dividido y un nuevo vértice se añadirá.
Los atributos de la capa vectorial y la longitud de un borde se puede utilizar como las propiedades de un borde.
La conversión de una capa vectorial al gráfico se realiza mediante el patrón de programación Constructor. Un gráfico
se construye utilizando el llamado Director. Solo hay un Director por ahora: QgsVectorLayerDirector. El
director establece la configuración básica que se utilizará para construir un gráfico a partir de una capa vectorial de
línea, utilizada por el constructor para crear el gráfico. Actualmente, como en el caso del director, solo existe un
constructor: QgsGraphBuilder, que crea objetos QgsGraph. Es posible que desee implementar sus propios
constructores que crearán un gráfico compatible con bibliotecas como BGL o NetworkX.
Para calcular las propiedades del borde, se usó el patrón de programación estrategia. Por ahora
solo estrategia QgsNetworkDistanceStrategy (que tiene en cuenta la longitud de la ruta) y
QgsNetworkSpeedStrategy (que también considera la velocidad) están disponibles. Puede implementar su
propia estrategia que utilizará todos los parámetros necesarios. Por ejemplo, el complemento RoadGraph utiliza una
estrategia que calcula el tiempo de viaje utilizando la longitud del borde y el valor de velocidad de los atributos.
Es tiempo de sumergirse en el proceso.
En primer lugar, para utilizar esta biblioteca debemos importar el módulo de análisis
Para construir un director, debemos pasar una capa vectorial que se utilizará como fuente para la estructura del
gráfico y la información sobre el movimiento permitido en cada segmento de la carretera (movimiento unidireccional
o bidireccional, dirección directa o inversa). La llamada se ve así
1 director = QgsVectorLayerDirector(vectorLayer,
2 directionFieldId,
3 directDirectionValue,
4 reverseDirectionValue,
5 bothDirectionValue,
6 defaultDirection)
Ahora podemos usar el constructor, que creará el gráfico. La clase QgsGraphBuilder constructor toma varios
argumentos:
• crs — sistema de referencia de coordenadas a utilizar. Argumento obligatorio.
• otfEnabled — usar reproyección «al vuelo» o no. Por defecto True (usa OTF).
• topologyTolerance — tolerancia topológica. Por defecto es 0.
• ellipsoidID — elipsoide a usar. Por defecto «WGS84».
# only CRS is set, all other values are defaults
builder = QgsGraphBuilder([Link]())
También podemos definir varios puntos, que se utilizarán en el análisis. Por ejemplo
startPoint = QgsPointXY(1179720.1871, 5419067.3507)
endPoint = QgsPointXY(1180616.0205, 5419745.7839)
Ahora todo está en su lugar para que podamos construir el gráfico y «atar» a estos puntos
tiedPoints = [Link](builder, [startPoint, endPoint])
Construir el grafo puede tomar tiempo (que depende del número de elementos y tamaño de una capa). tiedPoints
es una lista con coordenadas de puntos «tied». Cuando la operación de construcción se finalizo podemos obtener la
gráfica y utilizarlo para el análisis
graph = [Link]()
Con el siguiente código podemos obtener el índice del vértice de nuestros puntos
startId = [Link](tiedPoints[0])
endId = [Link](tiedPoints[1])
El análisis de redes es utilizado para encontrar respuestas a dos preguntas: que vértices estan conectados y cómo
encontrar la ruta más corta. Para resolver estos problemas la librería de análisis de redes proporciona el algoritmo
Dijkstra.
El algoritmo Dijkstra encuentra la ruta más corta de uno de los vértices del grafo a todos los otros y los valores de los
parámetros de optimización, El resultado puede ser representado como un árbol de la ruta más corta.
El árbol de ruta más corto es un gráfico ponderado dirigido (o más precisamente un árbol) con las siguientes
propiedades:
• sólo un vértice no tiene bordes entrantes — la raíz del árbol
• todos los otros vértices sólo tienen un borde entrante
• Si el vértice B es accesible desde el vértice A, entonces el camino de A a B es la única ruta disponible y es
optima (más corta) en este grafo
Para obtener la ruta del árbol más corta, use los métodos shortestTree() y dijkstra() de la clase
QgsGraphAnalyzer . Es recomendable usar el método dijkstra() porque funciona más rápido y usa la
memoria de manera más eficiente.
El método shortestTree() es útil cuando desea caminar alrededor del árbol del camino más corto. Siempre
crea un nuevo objeto gráfico (QgsGraph) y acepta tres variables:
• source — gráfica entrante
• startVertexIdx — índice del punto en el árbol (la raíz del árbol)
• criterionNum — número de propiedad de borde a usar (comenzando desde 0).
El método dijkstra() tiene los mismos argumentos, pero devuelve dos matrices. En el primer elemento de matriz,
n contiene el índice del borde entrante o -1 si no hay bordes entrantes. En el segundo elemento de matriz, n contiene
la distancia desde la raíz del árbol al vértice` n` o DOUBLE_MAX si el vértice n es inalcanzable desde la raíz.
Aquí hay un código muy simple para mostrar el árbol de ruta más corto usando el gráfico creado con el método
shortestTree() (seleccione la capa de cadena de líneas en el panel Capas y reemplace las coordenadas por las
suyas).
Advertencia: Use este código solo como ejemplo, crea muchos objetos QgsRubberBand y puede ser lento en
conjuntos de datos extensos.
7 vectorLayer = QgsVectorLayer('testdata/[Link]|layername=network_lines',
,→'lines')
13 pStart = QgsPointXY(1179661.925139,5419188.074362)
14 tiedPoint = [Link](builder, [pStart])
15 pStart = tiedPoint[0]
16
17 graph = [Link]()
18
19 idStart = [Link](pStart)
20
23 i = 0
24 while (i < [Link]()):
25 rb = QgsRubberBand([Link]())
26 [Link] ([Link])
27 [Link] ([Link]([Link](i).fromVertex()).point())
28 [Link] ([Link]([Link](i).toVertex()).point())
29 i = i + 1
7 vectorLayer = QgsVectorLayer('testdata/[Link]|layername=network_lines',
,→'lines')
10 strategy = QgsNetworkDistanceStrategy()
11 [Link](strategy)
12 builder = QgsGraphBuilder([Link]())
13
14 pStart = QgsPointXY(1179661.925139,5419188.074362)
15 tiedPoint = [Link](builder, [pStart])
16 pStart = tiedPoint[0]
17
18 graph = [Link]()
19
20 idStart = [Link](pStart)
21
Para encontrar la ruta óptima entre dos puntos, se utiliza el siguiente enfoque. Ambos puntos (inicio A y final B)
están «vinculados» al gráfico cuando se construye. Luego, usando el método shortestTree () o dijkstra()
construimos el árbol de ruta más corto con la raiz en el punto inicial A. En el mismo árbol también encontramos el
punto final B y comenzamos a caminar a través del árbol desde el punto B al punto A. Todo el algoritmo se puede
escribir como:
1 assign T = B
2 while T != B
3 add point T to path
4 get incoming edge for point T
5 look for point TT, that is start point of this edge
6 assign T = TT
7 add point A to path
En este punto tenemos la ruta, en el formulario de la lista invertida de vértices (los vértices están listados en orden
invertida del punto final al punto inicial) que serán visitados durante el viaje por este camino.
Aquí está el código de muestra para Consola de Pyhton QGIS (es posible que deba cargar y seleccionar
una capa de cadena de líneas en TOC y reemplazar las coordenadas en el código por las suyas) que usa el
método:meth:shortestTree() <[Link]>
8 vectorLayer = QgsVectorLayer('testdata/[Link]|layername=network_lines',
,→'lines')
9 builder = QgsGraphBuilder([Link]())
10 director = QgsVectorLayerDirector(vectorLayer, -1, '', '', '',␣
,→[Link])
11 strategy = QgsNetworkDistanceStrategy()
12 [Link](strategy)
13
14 startPoint = QgsPointXY(1179661.925139,5419188.074362)
15 endPoint = QgsPointXY(1180942.970617,5420040.097560)
16
20 graph = [Link]()
21 idxStart = [Link](tStart)
22
25 idxStart = [Link](tStart)
26 idxEnd = [Link](tStop)
27
28 if idxEnd == -1:
29 raise Exception('No route!')
30
43 # Display
44 rb = QgsRubberBand([Link]())
45 [Link]([Link])
46
8 vectorLayer = QgsVectorLayer('testdata/[Link]|layername=network_lines',
,→'lines')
10 strategy = QgsNetworkDistanceStrategy()
11 [Link](strategy)
12
13 builder = QgsGraphBuilder([Link]())
14
15 startPoint = QgsPointXY(1179661.925139,5419188.074362)
16 endPoint = QgsPointXY(1180942.970617,5420040.097560)
17
21 graph = [Link]()
22 idxStart = [Link](tStart)
23 idxEnd = [Link](tStop)
24
27 if tree[idxEnd] == -1:
28 raise Exception('No route!')
29
30 # Total cost
31 cost = costs[idxEnd]
32
41 # Display
42 rb = QgsRubberBand([Link]())
43 [Link]([Link])
(continúe en la próxima página)
El área de la disponibilidad para el vértice A es el subconjunto de vértices del grafo que son accesibles desde el vértice
A y el costo de los caminos de la A a estos vértices son no es mayor que cierto valor.
Más claramente esto se puede demostrar con el siguiente ejemplo: «Hay una estación de bomberos ¿Qué partes de
la ciudad puede un camión de bomberos alcanzar en 5 minutos? 10 minutos? 15 minutos?». Las respuestas a estas
preguntas son las zonas de la estación de bomberos de la disponibilidad.
Para encontrar las áreas de disponibilidad podemos usar el método dijkstra() de la clase
QgsGraphAnalyzer. Es suficiente comparar los elementos de la matriz de costos con un valor predefinido. Si el
costo [i] es menor o igual a un valor predefinido, entonces el vértice i está dentro del área de disponibilidad, de lo
contrario, está fuera.
Un problema más difícil es conseguir los límites de la zona de disponibilidad. El borde inferior es el conjunto de
vértices que son todavía accesibles, y el borde superior es el conjunto de vértices que no son accesibles. De hecho
esto es simple: es la frontera disponibilidad basado en los bordes del árbol de ruta más corta para los que el vértice
origen del contorno es más accesible y el vértice destino del borde no lo es.
Aquí tiene un ejemplo
2 strategy = QgsNetworkDistanceStrategy()
3 [Link](strategy)
4 builder = QgsGraphBuilder([Link]())
5
10 rb = QgsRubberBand([Link]())
11 [Link]([Link])
12 [Link](QgsPointXY(pStart.x() - delta, pStart.y() - delta))
13 [Link](QgsPointXY(pStart.x() + delta, pStart.y() - delta))
14 [Link](QgsPointXY(pStart.x() + delta, pStart.y() + delta))
15 [Link](QgsPointXY(pStart.x() - delta, pStart.y() + delta))
16
21 idStart = [Link](tStart)
22
25 upperBound = []
26 r = 1500.0
27 i = 0
28 [Link]()
29
37 for i in upperBound:
38 centerPoint = [Link](i).point()
39 rb = QgsRubberBand([Link]())
40 [Link]([Link])
41 [Link](QgsPointXY(centerPoint.x() - delta, centerPoint.y() - delta))
42 [Link](QgsPointXY(centerPoint.x() + delta, centerPoint.y() - delta))
43 [Link](QgsPointXY(centerPoint.x() + delta, centerPoint.y() + delta))
44 [Link](QgsPointXY(centerPoint.x() - delta, centerPoint.y() + delta))
20.1 Introducción
147
PyQGIS 3.40 developer cookbook
Las clases fundamentales involucradas en una aplicación típica de QGIS Server son:
• QgsServer la instancia del servidor (normalmente una sola instancia durante toda la vida de la aplicación)
• QgsServerRequest el objeto de la solicitud (normalmente recreado en cada solicitud)
• [Link](request, response) procesa la solicitud y completa la respuesta
El flujo de trabajo del servidor de desarrollo o FCGI de QGIS Server se puede resumir de la siguiente manera:
Advertencia: Las clases de servidor de QGIS no son seguras para subprocesos, siempre debe usar un modelo o
contenedores de multiprocesamiento cuando cree aplicaciones escalables basadas en la API de QGIS Server.
Para aplicaciones de servidor independientes o incrustaciones, deberá usar las clases de servidor mencionadas
anteriormente directamente, envolviéndolas en una implementación de servidor web que gestiona todas las
interacciones del protocolo HTTP con el cliente.
A continuación, se muestra un ejemplo mínimo del uso de la API de QGIS Server (sin la parte HTTP):
9 # Create the request by specifying the full URL and an optional body
10 # (for example for POST requests)
11 request = QgsBufferServerRequest(
12 '[Link] +
13 '&SERVICE=WMS&REQUEST=GetCapabilities')
14
21 print([Link]())
22 print([Link]().data().decode('utf8'))
(continúe en la próxima página)
24 [Link]()
A continuación se muestra un ejemplo completo de aplicación independiente desarrollada para las pruebas de
integraciones continuas en el repositorio de código fuente de QGIS, que muestra un amplio conjunto de diferentes
filtros de complementos y esquemas de autenticación (no significa para la producción, ya que se desarrollaron sólo
para fines de prueba, pero sigue siendo interesante para el aprendizaje): qgis_wrapped_server.py
Los complementos de Python del servidor se cargan una vez cuando se inicia la aplicación QGIS Server y se pueden
usar para registrar filtros, servicios o API.
La estructura de un complemento de servidor es muy similar a su contraparte de escritorio, un objeto
QgsServerInterface está disponible para los complementos y los complementos pueden registrar uno o más
filtros personalizados, servicios o API en el registro correspondiente mediante uno de los métodos expuestos por la
interfaz del servidor.
Los filtros vienen en tres sabores diferentes y se pueden instanciar subclasificando una de las clases a continuación y
llamando al método correspondiente de QgsServerInterface:
Filtros de E/S
Los filtros de E/S pueden modificar la entrada y salida del servidor (la solicitud y la respuesta) de los servicios
centrales (WMS, WFS, etc.) permitiendo realizar cualquier tipo de manipulación del flujo de trabajo de los servicios.
Es posible, por ejemplo, restringir el acceso a las capas seleccionadas, inyectar una hoja de estilo XSL a la respuesta
XML, agregar una marca de agua a una imagen WMS generada, etc.
A partir de este punto, encontrará útil un vistazo rápido a server plugins API docs.
Cada filtro debe implementar al menos una de las tres devoluciones de llamada:
• onRequestReady()
• onResponseComplete()
• onSendResponse()
Todos los filtros tienen acceso al objeto de solicitud/respuesta (QgsRequestHandler) y puede manipular todas
sus propiedades (entrada/salida) y generar excepciones (aunque de una manera bastante particular como veremos a
continuación).
Todos estos métodos devuelven un valor booleano que indica si la llamada debe propagarse a los filtros siguientes.
Si uno de estos métodos devuelve False entonces la cadena se detiene, de lo contrario la llamada se propagará al
siguiente filtro.
Aquí está el pseudocódigo que muestra cómo el servidor maneja una solicitud típica y cuándo se llaman las
devoluciones de llamada del filtro:
onRequestReady
Esto se llama cuando la solicitud está lista: la URL entrante y los datos se han analizado y antes de ingresar al
conmutador de servicios centrales (WMS, WFS, etc.), este es el punto donde puede manipular la entrada y realizar
acciones como:
• autenticación/autorización
• redirije
• añadir/borrar ciertos parámetros (nombres de tipos, por ejemplo)
• plantear excepciones
Incluso podría sustituir un servicio central por completo cambiando el parámetro SERVICE y, por lo tanto, omitiendo
el servicio central por completo (aunque esto no tiene mucho sentido).
onSendResponse
Esta llamada se realiza siempre que cualquier salida parcial se descarga desde el buffer de respuesta (es decir, a FCGI
stdout si se utiliza el servidor fcgi) y desde allí, al cliente. Esto ocurre cuando se transmite un contenido enorme
(como WFS GetFeature). En este caso onSendResponse() puede ser llamado varias veces.
Tenga en cuenta que si la respuesta no se transmite, entonces onSendResponse() no se llamará en absoluto.
En todos los casos, el último (o único) trozo se enviará al cliente tras una llamada a onResponseComplete().
Devolver False prevendrá la descarga de datos al cliente. Esto es deseable cuando un complemento quiere recoger
todos los trozos de una respuesta y examinar o cambiar la respuesta en onResponseComplete().
onResponseComplete
Se llama una vez cuando los servicios centrales (si se han alcanzado) terminan su proceso y la petición está lista para
ser enviada al cliente. Como se ha comentado anteriormente, este método se llamará antes de que el último (o único)
trozo de datos se envíe al cliente. Para servicios de streaming, multiples llamadas a onSendResponse() pueden
haber sido llamadas.
onResponseComplete() es el lugar ideal para proporcionar la implementación de nuevos servicios (WPS o
servicios personalizados) y para realizar la manipulación directa de la salida procedente de los servicios centrales
(por ejemplo para añadir una marca de agua sobre una imagen WMS).
Tenga en cuenta que devolver False evitará que los siguientes complementos ejecuten
onResponseComplete() pero, en cualquier caso, evitará que se envíe la respuesta al cliente.
Aún queda trabajo por hacer en este tema: la implementación actual puede distinguir entre excepciones manejadas y
no manejadas estableciendo una propiedad QgsRequestHandler a una instancia de QgsMapServiceException,
de esta manera el código principal de C ++ puede detectar excepciones de Python controladas e ignorar las excepciones
no controladas (o mejor: registrarlas).
Este enfoque básicamente funciona, pero no es muy «pitónico»: un mejor enfoque sería generar excepciones del
código de Python y verlas burbujear en el bucle C ++ para que se manejen allí.
Un complemento de servidor es un complemento estándar de QGIS Python como se describe en Desarrollando Plugins
Python, que solo proporciona una interfaz adicional (o alternativa): un complemento de escritorio QGIS típico tiene
acceso a la aplicación QGIS a través de: class:` QgisInterface <qgis. [Link]> , un complemento de servidor
solo tiene acceso a :class:`QgsServerInterface <[Link]> cuando se ejecuta dentro del contexto
de la aplicación QGIS Server.
Para que QGIS Server sepa que un complemento tiene una interfaz de servidor, se necesita una entrada de metadatos
especial (en [Link]):
server=True
Importante: QGIS Server solo cargará y ejecutará los complementos que tengan el conjunto de metadatos
server=True.
El complemento de ejemplo qgis3-server-vagrant discutido aquí (con muchos más) está disponible en github, algunos
complementos de servidor también están publicados en el repositorio oficial de complementos QGIS.
Archivos de complementos
1 PYTHON_PLUGINS_PATH/
2 HelloServer/
3 __init__.py --> *required*
4 [Link] --> *required*
5 [Link] --> *required*
__init__.py
Este archivo es requerido por el sistema de importación de Python. Además, QGIS Server requiere que este archivo
contenga una función serverClassFactory(), que se llama cuando el complemento se carga en QGIS Server
cuando se inicia el servidor. Recibe una referencia a la instancia de QgsServerInterface y debe devolver la
instancia de la clase de su complemento. Así es como se ve el complemento de ejemplo __init __. Py:
def serverClassFactory(serverIface):
from .HelloServer import HelloServerServer
return HelloServerServer(serverIface)
[Link]
Aquí es donde ocurre la magia y así es como se ve la magia: (por ejemplo [Link])
Un complemento de servidor generalmente consiste en una o más devoluciones de llamada empaquetadas en instancias
de QgsServerFilter.
Cada QgsServerFilter implementa una o más de las siguientes devoluciones de llamada:
• onRequestReady()
• onResponseComplete()
• onSendResponse()
El siguiente ejemplo implementa un filtro mínimo que imprime HelloServer! En caso de que el parámetro SERVICE
sea igual a «HELLO»:
1 class HelloFilter(QgsServerFilter):
2
class HelloServerServer:
def __init__(self, serverIface):
[Link](HelloFilter(serverIface), 100)
El segundo parámetro del método registerFilter() establece una prioridad que define el orden de las
devoluciones de llamada con el mismo nombre (la prioridad más baja se invoca primero).
Al utilizar las tres devoluciones de llamada, los complementos pueden manipular la entrada y / o la salida
del servidor de muchas formas diferentes. En todo momento, la instancia del complemento tiene acceso a
QgsRequestHandler a través de QgsServerInterface. La clase QgsRequestHandler tiene muchos
métodos que se pueden usar para modificar los parámetros de entrada antes de ingresar al procesamiento central del
servidor (usando requestReady()) o después de la solicitud ha sido procesado por los servicios centrales (usando
sendResponse()).
Los siguientes ejemplos cubren algunos casos comunes de uso:
Modificando la entrada
El complemento de ejemplo contiene un ejemplo de prueba que cambia los parámetros de entrada provenientes de
la cadena de consulta, en este ejemplo se inyecta un nuevo parámetro en el (ya analizado) parameterMap, este
parámetro es visible luego por los servicios centrales (WMS, etc.) , al final del procesamiento de los servicios centrales,
verificamos que el parámetro todavía esté allí:
1 class ParamsFilter(QgsServerFilter):
2
Truco: Si realmente desea implementar un servicio personalizado, se recomienda crear una subclase QgsService
y registre su servicio en registerFilter() llamando a su método registerService(service)
El ejemplo del filtro de marca de agua muestra cómo reemplazar la salida de WMS con una nueva imagen obtenida
agregando una imagen de marca de agua en la parte superior de la imagen de WMS generada por el servicio principal
de WMS:
5 class WatermarkFilter(QgsServerFilter):
6
23 p = QPainter(img)
24 [Link](QRect( 20, 20, 40, 40), watermark)
25 [Link]()
26 ba = QByteArray()
27 buffer = QBuffer(ba)
28 [Link]([Link])
29 [Link](buffer, "PNG" if "png" in [Link]("FORMAT") else
,→"JPG")
En este ejemplo, el valor del parámetro SERVICE se verifica y si la solicitud entrante es un WMS GETMAP y no
se han establecido excepciones por un complemento ejecutado previamente o por el servicio central (WMS en este
caso), la imagen generada por WMS se recupera del búfer de salida y se agrega la imagen de marca de agua. El último
paso es borrar el búfer de salida y reemplazarlo con la imagen recién generada. Tenga en cuenta que, en una situación
del mundo real, también deberíamos comprobar el tipo de imagen solicitada en lugar de admitir solo PNG o JPG.
Los filtros de control de acceso brindan al desarrollador un control detallado sobre las capas, características y atributos
a los que se puede acceder; las siguientes devoluciones de llamada se pueden implementar en un filtro de control de
acceso:
• layerFilterExpression(layer)
• layerFilterSubsetString(layer)
• layerPermissions(layer)
• authorizedLayerAttributes(layer, attributes)
• allowToEdit(layer, feature)
• cacheKey()
Archivos de complementos
__init__.py
Este archivo es requerido por el sistema de importación de Python. Como para todos los complementos del servidor
QGIS, este archivo contiene una función serverClassFactory (), que se llama cuando el complemento se
carga en el servidor QGIS al inicio. Recibe una referencia a una instancia de QgsServerInterface y debe
devolver una instancia de la clase de su complemento. Así es como el complemento de ejemplo __init__.py
aparece:
def serverClassFactory(serverIface):
from [Link] import AccessControlServer
return AccessControlServer(serverIface)
[Link]
1 class AccessControlFilter(QgsAccessControlFilter):
2
26 def cacheKey(self):
27 return super().cacheKey()
28
29 class AccessControlServer:
(continúe en la próxima página)
layerFilterExpression
layerFilterSubsetString
layerPermissions
authorizedLayerAttributes
allowToEdit
cacheKey
QGIS Server mantiene una caché de las capacidades entonces para tener una caché por rol puedes retornar el rol en
este método. O devolver None para desactivar completamente la caché.
En QGIS Server, los servicios centrales como WMS, WFS y WCS se implementan como subclases de QgsService.
Para implementar un nuevo servicio que se ejecutará cuando el parámetro de cadena de consulta SERVICE
coincida con el nombre del servicio, puedes implementar tu propio QgsService y registrar tu servicio en el
serviceRegistry() llamando a su registerService(service).
Este es un ejemplo de un servicio personalizado llamado CUSTOM:
1 from [Link] import QgsService
2 from [Link] import QgsMessageLog
3
4 class CustomServiceService(QgsService):
5
6 def __init__(self):
7 QgsService.__init__(self)
8
9 def name(self):
10 return "CUSTOM"
11
12 def version(self):
13 return "1.0.0"
14
20
21 class CustomService():
22
En QGIS Server, las API principales de OGC como OAPIF (también conocido como WFS3) se implementan
como colecciones de QgsServerOgcApiHandler subclases que están registradas en una instancia de
QgsServerOgcApi).
Para implementar una nueva API que se ejecute cuando la ruta url coincida con una determinada URL, puede
implementar sus propias instancias QgsServerOgcApiHandler, añadirlas a una QgsServerOgcApi y
registrar la API en el serviceRegistry() llamando a su registerApi(api).
A continuación, se muestra un ejemplo de una API personalizada que se ejecutará cuando la URL contenga /
customapi:
1 import json
2 import os
3
23
24 class CustomApiHandler(QgsServerOgcApiHandler):
25
26 def __init__(self):
27 super(CustomApiHandler, self).__init__()
28 [Link]([[Link], [Link]])
29
30 def path(self):
31 return QRegularExpression("/customapi")
32
33 def operationId(self):
34 return "CustomApiXYCircle"
35
36 def summary(self):
37 return "Creates a circle around a point"
38
39 def description(self):
40 return "Creates a circle around a point"
41
42 def linkTitle(self):
43 return "Custom Api XY Circle"
44
51 values = [Link](context)
52 x = values['x']
53 y = values['y']
54 r = values['r']
55 f = QgsFeature()
56 [Link]([x, y, r])
57 [Link](QgsCircle(QgsPoint(x, y), r).toCircularString())
58 exporter = QgsJsonExporter()
59 [Link]([Link]([Link](f)), context)
60
67 QgsServerQueryStringParameter(
68 'y', True, [Link], 'Y␣
,→coordinate'),
69 QgsServerQueryStringParameter('r', True,␣
,→[Link], 'radius')]
70
71
72 class CustomApi():
73
Consejo: Los fragmentos de código en esta página necesitan las siguientes adiciones si está fuera de la consola de
pyqgis:
1 from [Link] import (
2 QRectF,
3 )
4
Cambiar apariencia
1 from [Link] import QApplication
2
3 app = [Link]()
4 [Link](".QWidget {color: blue; background-color: yellow;}")
5 # You can even read the stylesheet from a file
6 with open("testdata/[Link]") as qss_file_content:
7 [Link](qss_file_content.read())
3 icon = QIcon("/path/to/logo/[Link]")
(continúe en la próxima página)
161
PyQGIS 3.40 developer cookbook
21.2 Configuración
3 qs = QgsSettings()
4
5 for k in sorted([Link]()):
6 print (k)
1 toolbar = [Link]()
2 parent = [Link]()
3 [Link](toolbar)
4
actions = [Link]().actions()
[Link]().clear()
[Link]().addAction(actions[4])
[Link]().addAction(actions[3])
21.4 Menús
Eliminar menú
21.5 Lienzo
Acceder al lienzo
canvas = [Link]()
[Link]().setCanvasColor([Link])
[Link]().refresh()
21.6 Capas
layer = [Link]("testdata/data/[Link]|layername=airports",
,→"Airports layer", "ogr")
layer = [Link]()
[Link]().mapLayers().values()
5 layers_names = []
6 for layer in [Link]().mapLayers().values():
7 layers_names.append([Link]())
8
De otra manera
Mostrar métodos
dir(layer)
3 feat = QgsFeature()
4 geom = QgsGeometry()
5 [Link](geom)
6 [Link]([Link]())
7
3 pr = [Link]()
4 feat = QgsFeature()
5 [Link]([Link](QgsPointXY(10,10)))
6 [Link]([feat])
for f in [Link]():
print (f)
for f in [Link]():
print (f)
memory_layer = [Link](QgsFeatureRequest().setFilterFids(layer.
,→selectedFeatureIds()))
[Link]().addMapLayer(memory_layer)
Obtener geometría
# Point layer
for f in [Link]():
geom = [Link]()
print ('%f, %f' % ([Link]().y(), [Link]().x()))
10.000000, 10.000000
Mover geometría
1 from [Link] import QgsFeature, QgsGeometry
2 poly = QgsFeature()
3 geom = [Link]("POINT(7 45)")
4 [Link](1, 1)
5 [Link](geom)
6 print([Link]())
Establecer SRC
from [Link] import QgsProject, QgsCoordinateReferenceSystem
Ver SRC
1 from [Link] import QgsProject
2
Ocultar columna
1 from [Link] import QgsEditorWidgetSetup
2
,→99,-88.82 34.99))")
7 [Link](geom)
8 [Link]([poly])
9 [Link]()
10 [Link]().addMapLayers([layer])
3 fileName = "testdata/[Link]"
4 layer = QgsVectorLayer(fileName, "test", "ogr")
5 subLayers = [Link]().subLayers()
6
7 urlWithParams = '[Link]
,→zmax=19&zmin=0&crs=EPSG3857'
8 loadXYZ(urlWithParams, 'OpenStreetMap')
[Link]().removeAllMapLayers()
Eliminar todos
[Link]().clear()
[Link]().layers()
1 ltv = [Link]()
2 mp = [Link]()
3 [Link](None)
4 # Restore
5 [Link](mp)
Nodo raíz
3 root = [Link]().layerTreeRoot()
4 node_group = [Link]("My Group")
5
9 node_group.addLayer(layer)
10
11 print(root)
12 print([Link]())
3 child0 = [Link]()[0]
4 print ([Link]())
5 print (type(child0))
6 print (isinstance(child0, QgsLayerTreeLayer))
7 print (isinstance([Link](), QgsLayerTree))
My Group
<class 'qgis._core.QgsLayerTreeGroup'>
False
True
3 def get_group_layers(group):
4 print('- group: ' + [Link]())
5 for child in [Link]():
6 if isinstance(child, QgsLayerTreeGroup):
7 # Recursive call to get nested groups
8 get_group_layers(child)
9 else:
10 print(' - layer: ' + [Link]())
(continúe en la próxima página)
12
13 root = [Link]().layerTreeRoot()
14 for child in [Link]():
15 if isinstance(child, QgsLayerTreeGroup):
16 get_group_layers(child)
17 elif isinstance(child, QgsLayerTreeLayer):
18 print ('- layer: ' + [Link]())
- group: My Group
- layer: layer name you like
<QgsLayerTreeGroup: My Group>
print([Link]([Link]()))
Añadir capas
Añadir grupo
4 myLayer = [Link]([Link]())
5 myClone = [Link]()
6 parent = [Link]()
7
12 [Link](myLayer)
1 [Link]().addMapLayer(layer, False)
2
3 root = [Link]().layerTreeRoot()
4 myGroup = [Link]("My Group")
5 myOriginalLayer = [Link]([Link]())
6 myLayer = [Link]()
7 [Link](0, myLayer)
8 [Link](myOriginalLayer)
root = [Link]().layerTreeRoot()
node = [Link]([Link]())
new_state = [Link] if [Link]() == [Link] else [Link]
[Link](new_state)
Es el grupo seleccionado
False
Expandir nodo
print([Link]())
[Link](False)
3 model = [Link]().layerTreeModel()
4 ltv = [Link]()
5 root = [Link]().layerTreeRoot()
6
Señales de nodo
7 [Link](onWillAddChildren)
8 [Link](onAddedChildren)
Eliminar capa
[Link](layer)
Eliminar grupo
[Link](node_group2)
1 root = [Link]().layerTreeRoot()
2 model = QgsLayerTreeModel(root)
3 view = QgsLayerTreeView()
4 [Link](model)
5 [Link]()
Mover nodo
cloned_group1 = node_group.clone()
[Link](0, cloned_group1)
[Link](node_group)
cloned_group1.setName("Group X")
node_layer1.setName("Layer X")
...
Ejecutar algoritmo
Para este ejemplo, el resultado se almacena en una capa en memoria que se agrega al proyecto.
len([Link]().algorithms())
len([Link]().providers())
len([Link]())
21.10 Decoradores
CopyRight
19 def _on_render_complete(p):
20 deviceHeight = [Link]().height() # Get paint device height on which this␣
,→painter is currently painting
33 # RenderMillimeters
34 pixelsInchX = [Link]().logicalDpiX()
35 pixelsInchY = [Link]().logicalDpiY()
36 xOffset = pixelsInchX * INCHES_TO_MM * int(mMarginHorizontal)
37 yOffset = pixelsInchY * INCHES_TO_MM * int(mMarginVertical)
38
39 # Calculate positions
40 if case == 0:
41 # Top Left
42 add_copyright(p, text, xOffset, yOffset)
43
49 elif case == 2:
50 # Top Right
51 xOffset = deviceWidth - xOffset - [Link]()
52 add_copyright(p, text, xOffset, yOffset)
53
54 elif case == 3:
55 # Bottom Right
56 yOffset = deviceHeight - yOffset - [Link]()
57 xOffset = deviceWidth - xOffset - [Link]()
58 add_copyright(p, text, xOffset, yOffset)
59
60 elif case == 4:
61 # Top Center
62 xOffset = deviceWidth / 2
63 add_copyright(p, text, xOffset, yOffset)
64
65 else:
66 # Bottom Center
67 yOffset = deviceHeight - yOffset - [Link]()
68 xOffset = deviceWidth / 2
69 add_copyright(p, text, xOffset, yOffset)
70
21.11 Compositor
3 project = [Link]()
4 projectLayoutManager = [Link]()
5 layout = [Link](composerTitle)
21.12 Fuentes