Faça uma atualização da camada Qgis a partir de uma fonte de dados alterada


13

Estou tentando fazer com que as camadas sejam atualizadas automaticamente quando a fonte de dados muda. Estou usando R para escrever um shapefile com um atributo e colorir de acordo com esse atributo no QGIS.

Quero escrever um novo shapefile com diferentes valores de atributo e atualizar as cores do mapa Qgis. A etapa 1 está iniciando esse processo, a etapa 2 está recarregando a camada a partir do shapefile modificado. Seu passo 2, estou me preocupando aqui.

Outras perguntas / conversas na lista de discussão mencionam o uso triggerRepaintna camada - isso não funciona. Outras sugestões incluem setCacheImage(None)e novamente que não funciona. A camada é atualizada eventualmente, mas eu realmente não consigo ver a lógica e, às vezes, acontece de surpresa depois que não faço nada. Ou talvez eu tenha feito algo dois minutos atrás.

A única maneira reproduzível de fazer a atualização é duplicar a camada no menu de legenda - a duplicata sempre obtém seus dados do shapefile atual e a camada original também se atualiza! Portanto, deve haver alguma maneira de fazê-lo.

Eu acho que estava funcionando melhor no 2.8, mas esse é o 2.10, então talvez haja um novo bug em algum lugar.

Relacionado, mas não funciona para mim na versão 2.10:

Como recarregar automaticamente as camadas de varredura se a origem for alterada no QGIS?

Outras coisas que eu tentei:

  • layer.dataProvider().dataChanged.emit() - trabalhou uma vez, depois não novamente na mesma camada

Acho que rastreei por que a duplicação da camada funciona - se eu criar uma nova camada descartável com base na camada atualizada e depois ligar .triggerRepaint()para a camada atualizada, ela será atualizada na tela do mapa:

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

Se eu usar uma fonte de camada diferente, ela não funcionará, então parece que se você criar um objeto de camada com base na mesma fonte de camada ...

Um teste rápido agora com uma camada de varredura (de um GeoTIFF), e apenas a chamada rlayer.triggerRepaint()parece atualizar de forma confiável a exibição da varredura na tela do mapa.


Pode ser necessário publicar um código de exemplo.
21715 Nathan W

@ Nathanathan A maior parte do que estou fazendo é a partir da camada gui - load, style it - e, em seguida, apenas obtendo a camada e as poucas linhas no console do Python. Estou inclinado a colocar isso na estrutura de um plug-in até saber que posso fazer o princípio funcionar! Eu esperava que houvesse uma resposta rápida ("chamada layer.updateFromNewDataYouFool ()"), mas preencherei isso com mais código (incluindo o código R para criar os shapefiles) mais tarde.
Spacedman

Para ter certeza, você tentou usar os dois comandos posteriormente: layer.setCacheImage(None)e layer.triggerRepaint()?
Matthias Kuhn

Sim @MatthiasKuhn - embora às vezes isso funcione, mas não com frequência. Acabei de escrever um shapefile modificado, fiz as duas coisas no console Python (na camada direita), sem atualização visual. A coisa mais simples que funcionou 100% até agora é criar um novo objeto de camada descartável com base na origem da camada original, como mencionado acima, e depois triggerRepaint()na camada original. v 2.10.1-Pisa
Spacedman

Suspeito que isso possa estar relacionado à introdução do pool de conexões OGR. Você pode executar alguns testes se houver uma diferença se substituir o arquivo no disco ou editar o arquivo existente?
Matthias Kuhn

Respostas:


5

Isso está relacionado à introdução do conjunto de conexões OGR. [1]

Antes do QGIS 2.10, um arquivo era reaberto em todos os acessos (por exemplo, repintar).

Desde o QGIS 2.10, o identificador de arquivo é mantido aberto e isso significa que, se um arquivo for substituído, o identificador ainda aponta para o arquivo antigo em sistemas baseados em Unix.

QGIS 2.10: solução alternativa

Infelizmente, não há API para forçar o QGIS a reabrir o arquivo no QGIS 2.10. Como solução alternativa, você pode usar um truque feio:

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

QGIS 2.12: solução

Acabei de introduzir um novo método que estará disponível a partir do QGIS 2.12:

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

Abordagem geral

Se você tiver a possibilidade de controlar como o arquivo está sendo substituído, poderá abrir os arquivos existentes com permissões de gravação e alterar o conteúdo em vez de substituí-los completamente (excluir / recriar) no disco.

[1] O pool de conexões foi introduzido para acelerar significativamente o acesso a determinadas fontes de dados.


Parece a melhor solução. O .changeAttributeValuestraz-se uma "ERRO 1: Tentativa para ler forma com ID de recurso (-1) fora da faixa disponível." Mas está tudo bem.
Spacedman

2

Se você deslocar ou atualizar o mapa, ele deverá ser atualizado.

Este artigo diz que você pode usar o seguinte no PyQGIS:

myLayer.triggerRepaint()

Para atualizar todas as camadas, a seguinte função pode ser usada:

def refresh_layers(self):
    for layer in qgis.utils.iface.mapCanvas().layers():
         layer.triggerRepaint()

Como eu disse na minha pergunta, e como mencionado no link que eu dei, triggerRepaint()não funciona. refresh()na tela do mapa não funciona. Definir a imagem do cache como None(que agora está obsoleta nos documentos da API) não funciona. Eu apenas tentei todas essas coisas em uma camada de shapefile recém-modificada, percorri o mapa, alternei entre o visual e o off, não funcionou. "Duplicar" a camada e ela é atualizada instantaneamente. Você já tentou essas coisas (na versão 2.10)?
Spacedman 28/08/15

Acho que precisamos de @ nathan-w para responder a isso. Eu não tentei me ...
Alex Leith

Tentei em #qgis no IRC, mas talvez eu preciso para deixar a lista de discussão qgis-dev ...
Spacedman
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.