Realice una actualización de la capa Qgis desde un origen de datos modificado

13

Estoy tratando de hacer que las capas se actualicen automáticamente cuando cambia su fuente de datos. Estoy usando R para escribir un shapefile con un atributo y colorear de acuerdo con ese atributo en QGIS.

Quiero escribir un nuevo shapefile con diferentes valores de atributo y hacer que se actualicen los colores del mapa Qgis. El paso 1 está activando ese proceso, el paso 2 está haciendo que la capa se vuelva a cargar desde el archivo de forma modificado. Su paso 2 me preocupa aquí.

Otras preguntas / conversaciones de listas de correo mencionan el uso triggerRepainten la capa, eso no funciona. Otras sugerencias incluyen setCacheImage(None)y nuevamente eso no funciona. La capa se actualiza eventualmente, pero realmente no puedo ver la lógica, y a veces sucede por sorpresa después de no haber hecho nada. O tal vez hice algo hace dos minutos.

La única forma reproducible de hacer que se actualice es duplicar la capa desde el menú de la leyenda: el duplicado siempre obtiene sus datos del archivo de forma actual, ¡y la capa original también se actualiza a sí misma! Entonces debe haber alguna forma de hacerlo.

Creo que funcionaba mejor en 2.8, pero esto es 2.10, así que tal vez haya un nuevo error en alguna parte.

Relacionado, pero no funciona para mí en 2.10:

¿Cómo recargar automáticamente las capas ráster si la fuente se cambia en QGIS?

Otras cosas que he probado:

  • layer.dataProvider().dataChanged.emit() - trabajó una vez, luego no otra vez en la misma capa

Creo que he rastreado por qué funciona la duplicación de la capa: si creo una nueva capa desechable basada en la capa actualizada y luego llamo .triggerRepaint()a la capa actualizada, se actualiza en el lienzo del mapa:

QgsVectorLayer( layer.source(), "layer copy", layer.providerType() )
layer.triggerRepaint()

Si uso una fuente de capa diferente, no funciona, por lo que parece ser si creas un objeto de capa basado en la misma fuente de capa ...

Una prueba rápida en este momento con una capa ráster (desde un GeoTIFF), y solo llamar rlayer.triggerRepaint()parece actualizar de manera confiable la vista del ráster en el lienzo del mapa.

Hombre espacial
fuente
Es posible que deba publicar un código de muestra.
Nathan W
@NathanW, la mayor parte de lo que estoy haciendo es desde la capa de carga de interfaz gráfica de usuario (GUI), luego de obtener la capa y esas pocas líneas en la consola de Python. ¡No estoy dispuesto a pegar esto en el marco de un complemento hasta que sepa que puedo hacer que el principio funcione! Esperaba que hubiera una respuesta rápida ("call layer.updateFromNewDataYouFool ()") pero completaré esto con más código (incluido el código R para hacer los archivos de forma) más adelante.
Spacedman
Para estar seguro, intentó usar ambos comandos posteriormente: layer.setCacheImage(None)y layer.triggerRepaint()?
Matthias Kuhn
Sí @MatthiasKuhn, aunque a veces eso funciona, pero no con frecuencia. Acabo de escribir un archivo de forma modificado, hice ambas cosas en la consola de Python (en la capa derecha), sin actualización visual. Lo más simple que ha funcionado al 100% hasta ahora es crear un nuevo objeto de capa desechable basado en la fuente de capa original como se mencionó anteriormente y luego triggerRepaint()en la capa original. v 2.10.1-Pisa
Spacedman
Tengo la sospecha de que esto podría estar relacionado con la introducción del grupo de conexiones OGR. ¿Puede realizar algunas pruebas si hay una diferencia si reemplaza el archivo en el disco o edita el archivo existente?
Matthias Kuhn

Respuestas:

5

Esto está relacionado con la introducción del grupo de conexiones OGR. [1]

Antes de QGIS 2.10, se volvía a abrir un archivo en cada acceso individual (por ejemplo, repintar).

Desde QGIS 2.10, el identificador de archivo se mantiene abierto y esto significa que si se reemplaza un archivo, el identificador todavía apunta al archivo antiguo en sistemas basados ​​en Unix.

QGIS 2.10: solución alternativa

Desafortunadamente, no hay una API que obligue a QGIS a volver a abrir el archivo en QGIS 2.10. Como solución alternativa, puede usar un truco feo:

layer.dataProvider().changeAttributeValues( { -1: { 0: 0 } } )
layer.triggerRepaint()

QGIS 2.12: solución

Acabo de presentar un nuevo método que estará disponible a partir de QGIS 2.12:

layer.dataProvider().forceReload()
layer.triggerRepaint()

Enfoque general

Si tiene la posibilidad de controlar cómo se sobrescribe el archivo, puede abrir los archivos existentes con permisos de escritura y cambiar el contenido en lugar de reemplazar los archivos por completo (eliminar / recrear) en el disco.

[1] El conjunto de conexiones se introdujo para acelerar significativamente el acceso a ciertas fuentes de datos.

Matthias Kuhn
fuente
Parece la mejor solución. El .changeAttributeValuesnos lleva a un "error 1: intento de leer la forma con la función Identificación del (-1) fuera del rango disponible." pero eso está bien.
Spacedman
2

Si realiza una panorámica o actualiza el mapa, debería actualizarse.

Este artículo dice que puede usar lo siguiente en PyQGIS:

myLayer.triggerRepaint()

Para actualizar todas las capas se puede usar la siguiente función:

def refresh_layers(self):
    for layer in qgis.utils.iface.mapCanvas().layers():
         layer.triggerRepaint()
Alex Leith
fuente
Como dije en mi pregunta, y como mencioné en el enlace que di, triggerRepaint()no funciona. refresh()en el mapa el lienzo no funciona. Establecer la imagen de caché en None(que ahora está en desuso en los documentos de la API) no funciona. Acabo de probar todas estas cosas en una capa de archivo de forma recién modificada, recorrí el mapa, cambié la vista de vez en cuando, no funcionó. Sin embargo, "duplica" la capa y se actualiza instantáneamente. ¿Has probado estas cosas tú mismo (en 2.10)?
Spacedman
Creo que necesitamos @ nathan-w para responder esto. No lo he probado yo mismo ...
Alex Leith
Probé en #qgis en IRC pero tal vez necesito publicar en la lista de correo qgis-dev ...
Spacedman