使QGIS属性表字段自动执行?


9

我正在以某种方式使用QGIS和我拥有的Excel工作表进行水文项目。为此,我想提取包含在代表管道截面的矢量层中的线的一些信息。

我需要提取的信息是:

  • 身份证号
  • 长度
  • X,Y起始和结束坐标

我找到了一种使用“ $ length”和另一种用于X和Y坐标的算法捕获该字段的方法,但是为此,我需要打开Attributes表,将表达式放在每个属性列中,然后单击以更新字段。

当我画一条线时,有没有办法自动填写这些字段?也就是说,我绘制/编辑一条线(开始编辑或结束节点),当我打开属性表时,将填充并更新长度字段和坐标X,Y。


1
暂时无法确定是否处于编辑模式(因为在临时表中已完成)。但是您可能会看看动作。例如,您可以使用它们来运行python代码来填写您的计算。那么,您必须按下一个额外的按钮才能从属性表中运行它。您可以查看存在的可能性,并查看它是否符合您的想法。
Matte

Answers:


7

如果仅在QGIS中需要这些字段,则可以使用虚拟字段。这些允许使用$length依赖于其他值或几何的表达式(如)。

打开字段计算器,添加名称长度的新字段,选中“虚拟字段”复选框,然后输入$length表达式(或其他字段)。

但是,这些不会保存到excel文件中。

如果要使excel文件与用于几何的shp文件保持同步,并在excel文件中包括派生字段,则有一个名为ShpSync的插件可以识别此概念,并在更改,添加或删除要素时自动更新字段。


实际上,下面的答案完全可以满足我的要求,但是您所说的此插件将在我的项目的下一步工作。谢谢你的帮助
LeoNazareth

15

有趣的问题!我不知道有什么其他方法可以实现所需的功能,但可以使用PyQGIS。

阅读下面的代码。它里面有一些文字:'lines''length''startX''startY''endX''endY'。您可以在脚本中调整这些名称,以使其在数据上起作用。第一个是您的图层名称,其余的则对应于字段名称。我假设您的线层具有这些字段(毕竟,您希望将值写入那里)。

调整图层名称和要自动更新的字段的名称后,将脚本复制并粘贴到QGIS Python控制台中。

如果一切顺利,您应该能够在两种情况下看到字段值自动更新:1)添加新要素时,以及2)修改几何时。

# Initialize required variables
myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'lines' )[0]
lengthField = myLayer.fieldNameIndex( 'length' )
startXField = myLayer.fieldNameIndex( 'startX' )
startYField = myLayer.fieldNameIndex( 'startY' )
endXField = myLayer.fieldNameIndex( 'endX' )
endYField = myLayer.fieldNameIndex( 'endY' )

# Slot, updates field values
def updateFeatureAttrs( fId, geom=None ):
    f = myLayer.getFeatures( QgsFeatureRequest( fId ) ).next()    
    if not geom:
        geom = f.geometry() 
    myLayer.changeAttributeValue( fId, lengthField, geom.length() )
    myLayer.changeAttributeValue( fId, startXField, geom.vertexAt( 0 )[0] )
    myLayer.changeAttributeValue( fId, startYField, geom.vertexAt( 0 )[1] )
    myLayer.changeAttributeValue( fId, endXField, geom.asPolyline()[-1][0] )
    myLayer.changeAttributeValue( fId, endYField, geom.asPolyline()[-1][1] )

# Update feature attributes when new features are added or geometry changes
myLayer.featureAdded.connect( updateFeatureAttrs )
myLayer.geometryChanged.connect( updateFeatureAttrs )

它是这样工作的:

自动更新QGIS中的字段

如果在运行脚本时遇到任何问题,请在此答案下方添加注释。

当您打开QGIS项目时,使该功能已经可用可能很方便。如果是这样,请告诉我,我可以发布相关说明。


编辑:

为了使此功能在您每次打开QGIS项目(例如.qgs,其中包含您的行图层的文件)时都可用,您需要执行以下步骤:

  1. 转至QGIS->Project->Project Properties->Macros,选中该Python macros选项,然后用该代码替换整个代码(调整表示您的图层和字段名称的值):

    from qgis.core import QgsMapLayerRegistry, QgsFeatureRequest
    def openProject():    
        # Initialize required variables
        myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'lines' )[0]
    
        # Update feature attributes when new features are added or geometry changes
        myLayer.featureAdded.connect( updateFeatureAttrs )
        myLayer.geometryChanged.connect( updateFeatureAttrs )
    
    # Slot, updates field values
    def updateFeatureAttrs( fId, geom=None ):
        myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'lines' )[0]
        lengthField = myLayer.fieldNameIndex( 'length' )
        startXField = myLayer.fieldNameIndex( 'startX' )
        startYField = myLayer.fieldNameIndex( 'startY' )
        endXField = myLayer.fieldNameIndex( 'endX' )
        endYField = myLayer.fieldNameIndex( 'endY' )
        f = myLayer.getFeatures( QgsFeatureRequest( fId ) ).next()    
        if not geom:
            geom = f.geometry() 
        myLayer.changeAttributeValue( fId, lengthField, geom.length() )
        myLayer.changeAttributeValue( fId, startXField, geom.vertexAt( 0 )[0] )
        myLayer.changeAttributeValue( fId, startYField, geom.vertexAt( 0 )[1] )
        myLayer.changeAttributeValue( fId, endXField, geom.asPolyline()[-1][0] )
        myLayer.changeAttributeValue( fId, endYField, geom.asPolyline()[-1][1] )
    
    def saveProject():
        pass
    
    def closeProject():
        pass
  2. 确保通过以下方式在项目中启用宏:Settings->Options->General->Enable macros: Always

  3. 保存您的QGIS项目。

现在,每次打开.qgs刚刚保存的文件时,当您添加新功能或修改几何时(即不再需要将任何内容复制到QGIS Python控制台中),线图层的属性都会自动更新。


第二次编辑:

我刚刚发布了一个名为AutoFields的插件,以帮助人们解决此类问题。我什至制作了一段视频,展示如何解决您的问题,您可以在以下位置观看:

https://vimeo.com/germap/autofields-geometric-properties

AutoFields文档:http ://geotux.tuxfamily.org/index.php/en/geo-blogs/item/333-autofields-plugin-for-qgis


2
这正是我想要的。实际上,我在用您的代码捕获X,Y坐标,这是您在此帖子链接的旧答案中找到的,与您现在发布的相同。我已经对自动化进行了测试,并且效果很好。我将Python代码保存为文件“ .pycl”。如果您可以向我解释一下,当我打开QGIS项目时如何使用它会很棒。谢谢您的帮助。
LeoNazareth '16

1
德语,这是一个了不起的答案!谢谢!我从您那里学到了很多东西!
jbgramm '16

1
我实际上正在开发一个插件,它将使您能够做到这一点。由于我只能将自己的业余时间用于开发,所以无法告诉您预计的发布日期。同时,您可以在添加Tramo.shp之后运行我的第一个代码段,并进行以下调整:myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'Tramo' )[0]如果您对我的未来插件确实很感兴趣,请给我任何建议,我将不胜感激。您可以通过GeoTux与我联系。
赫尔曼·卡里略

1
这对我(对许多人来说当然)非常好,我已经在使用您建议的这种调整的代码了。我会焦急地等待您的新插件,如果我认为有用的话,请与您联系。谢谢你为我做的一切。
LeoNazareth

1
@LeoNazareth,您要测试插件吗?它已经准备就绪,但是我想在发布之前进行一些测试。如果您愿意进行测试,请给我发送电子邮件
赫尔曼Carrillo的

2

对于QGIS 3,请转到Layers Properties=> Attributes Form=>选择带有几何值的字段(例如area)=> $areaDefaults value框中键入并选中Apply default value on update。这也可能是有用的:$perimeter$y$x$id


1

我会将数据放入数据库(PostGIS)中,然后使用(可能是实体化的)视图将数据提取到QGIS中。

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.