从更改的数据源进行Qgis图层更新


13

我试图让图层在其数据源更改时自动更新。我正在使用R编写具有属性的shapefile,并根据QGIS中的该属性进行着色。

我想编写一个具有不同属性值的新shapefile,并更新Qgis贴图颜色。第1步触发该过程,第2步从修改后的shapefile重新加载图层。我在这里担心它的第2步。

其他问题/邮件列表聊天者提到triggerRepaint了在图层上使用的内容-不起作用。其他建议包括setCacheImage(None)一遍又一遍不起作用。该层确实会最终更新,但是我真的看不到逻辑,有时在我什么都不做之后会意外地发生。或者也许我在两分钟前做了一些事情。

一种可更新的更新方式是从图例菜单中复制图层-副本始终从当前shapefile获取其数据,而原始图层也将自行更新!因此,必须有某种方法可以做到这一点。

我认为它在2.8中工作得更好,但这是2.10,因此也许某个地方存在一个新的错误。

相关,但在2.10中不适用于我:

如果在QGIS中更改了源,如何自动重新加载栅格图层?

我尝试过的其他方法:

  • layer.dataProvider().dataChanged.emit() -工作一次,然后不在同一层上工作

我想我已经找到了为什么要复制图层的原因-如果我基于更新的图层创建一个新的一次性图层,然后调用.triggerRepaint()更新的图层,它将在地图画布上更新:

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

如果我使用不同的图层源,它将无法正常工作,因此似乎是基于相同图层源创建图层对象的。

现在,使用栅格图层(来自GeoTIFF)进行快速测试,并且只需调用rlayer.triggerRepaint()即可可靠地更新地图画布中栅格的视图。


您可能需要发布一些示例代码。
内森·W

@NathanW我所做的大部分工作都来自gui-加载层,对其进行样式设置-然后仅获取该层以及Python控制台中的那几行内容。我不愿意将其坚持在插件的框架中,直到我知道我可以使原理起作用为止!我希望能有一个快速的答案(“ call layer.updateFromNewDataYouFool()”),但稍后我将用更多代码(包括用于制作shapefile的R代码)进行填充。
Spacedman

可以肯定的是,您随后尝试使用这两个命令:layer.setCacheImage(None)layer.triggerRepaint()
马提亚斯·库恩

是的@MatthiasKuhn-尽管有时可行,但并不常见。我只是编写了一个修改过的shapefile,在Python控制台(在右层)上做了这两个事情,没有视觉更新。到目前为止,最简单的方法已100%起作用,它是基于如上所述的原始图层源然后triggerRepaint()在原始图层上创建一个新的一次性图层对象。v
2.10.1-

我怀疑这可能与OGR连接池的引入有关。如果替换磁盘上的文件或编辑现有文件,是否可以执行某些测试以区别它们?
Matthias Kuhn,2015年

Answers:


5

这与OGR连接池的引入有关。[1]

在QGIS 2.10之前,每次访问都重新打开一个文件(例如,重新绘制)。

从QGIS 2.10开始,文件句柄保持打开状态,这意味着如果替换了文件,该句柄仍指向基于Unix的系统上的旧文件

QGIS 2.10:解决方法

不幸的是,没有API可以很好地强制QGIS在QGIS 2.10中重新打开文件。作为一种解决方法,您可以使用丑陋的hack:

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

QGIS 2.12:解决方案

我刚刚介绍了一种新方法,将从QGIS 2.12开始使用:

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

一般的做法

如果你有可能性,控制如何在文件被覆盖,你可以用写权限打开现有的文件和修改内容,而不是完全替换文件(删除/重新创建)在磁盘上的。

[1]引入连接池可显着加快对某些数据源的访问。


看起来是最好的解决方案。在.changeAttributeValues带来了一个“ERROR 1:尝试与特征ID读取形状(-1)的可用范围的”。没关系
Spacedman

2

如果平移或刷新地图,则应该更新。

本文说您可以在PyQGIS中使用以下内容:

myLayer.triggerRepaint()

要刷新所有层,可以使用以下功能:

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

正如我在问题中所说的那样,并且正如我在链接中所提到的那样,triggerRepaint()它不起作用。refresh()在地图画布上不起作用。将缓存图片设置为None(API文档中现已弃用)不起作用。我只是在一个新修改的shapefile层上尝试了所有这些操作,平移了地图,打开和关闭vis,这没有用。“复制”该图层,但它会立即更新。您自己(在2.10上)尝试过这些东西吗?
Spacedman

我认为我们需要@ nathan-w来回答这个问题。我自己还没有尝试过...
Alex Leith

我在IRC上尝试使用#qgis,但也许我需要将其发布到qgis-dev邮件列表中……
Spacedman
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.