PyQGIS笔记
添加栅格
PROJECT = QgsProject.instance()
rlayer = QgsRasterLayer(file_path, name)
if not rlayer.isValid():
QMessageBox.information(self, '信息', '图像图层加载失败!')
else:
PROJECT.addMapLayer(rlayer) # 将图层添加到mapcanvas以及目录树根节点,并可以通过目录树进行控制
# PROJECT.addMapLayer(rlayer, False) # 将图层添加到mapcanvas,但不能通过目录树进行控制
向根节点添加图层组
root = PROJECT.layerTreeRoot()
root.addGroup('aa')
根据名称查询图层组
group1 = root.findGroup('aa') # 获取名字为aa的图层组
group2 = group1.findGroup('bb') # 获取aa图层组下的bb图层组
向图层组图层,并加载到mapcanvas中
group2.addLayer(rlayer)
PROJECT.addMapLayer(rlayer, False) # 添加图层到canvas中,但不添加到TOC中
添加矢量
# 加载矢量图层到根节点和mapcanvas中
vlayer = QgsVectorLayer(file_path, name)
PROJECT.addMapLayer(vlayer)
# 加载矢量图层到指定图层组和mapcanvas中
group2.addLayer(vlayer)
PROJECT.addMapLayer(vlayer, False)
缩放到全图
self.mapCanvas = QgsMapCanvas(self)
def zoomToMap(self):
'''缩放到全图'''
self.mapCanvas.zoomToFullExtent()
self.mapCanvas.enableAntiAliasing(True)
拉框放大
class ZoomInTool(QgsMapToolZoom):
'''拉框放大'''
def __init__(self, mapCanvas):
super(ZoomInTool, self).__init__(mapCanvas, False)
self.mapCanvas = mapCanvas
self.rubberBand = QgsRubberBand(mapCanvas, QgsWkbTypes.PolygonGeometry)
self.rubberBand.setColor(QColor(0, 0, 255, 100))
self.rubberBand.setWidth(1)
self.reset()
def reset(self):
'''重置拉框放大的参数'''
self.startPoint = self.endPoint = None
self.isPressed = False
self.rubberBand.reset(QgsWkbTypes.PolygonGeometry)
# 鼠标按下事件,获取起始坐标
def canvasPressEvent(self, e):
self.startPoint = self.toMapCoordinates(e.pos())
self.endPoint = self.startPoint
self.showRect(self.startPoint, self.endPoint)
self.isPressed =True
# 鼠标松开事件
def canvasReleaseEvent(self, e):
self.isPressed = False
x = e.pos().x()
y = e.pos().y()
r = self.getRectangle()
self.mapCanvas.setExtent(r) # 将绘制的矩形范围赋给当前画布即可实现拉框放大
self.mapCanvas.refresh() # 刷新当前画布
self.reset()
def canvasMoveEvent(self, e):
if not self.isPressed:
return
self.endPoint = self.toMapCoordinates(e.pos())
self.showRect(self.startPoint, self.endPoint)
def showRect(self, startPoint, endPoint):
'''显示拉框'''
self.rubberBand.reset(QgsWkbTypes.PolygonGeometry)
if startPoint.x() == endPoint.x() or startPoint.y() == endPoint.y():
return
point1 = QgsPointXY(startPoint.x(), startPoint.y())
point2 = QgsPointXY(startPoint.x(), endPoint.y())
point3 = QgsPointXY(endPoint.x(), endPoint.y())
point4 = QgsPointXY(endPoint.x(), startPoint.y())
self.rubberBand.addPoint(point1, False)
self.rubberBand.addPoint(point2, False)
self.rubberBand.addPoint(point3, False)
self.rubberBand.addPoint(point4, True)
self.rubberBand.show()
def getRectangle(self):
'''判断是否为矩形拉框,并获取矩形范围'''
if self.startPoint is None or self.endPoint is None:
return None
elif self.startPoint.x() == self.endPoint.x() or self.startPoint.y() == self.endPoint.y():
return None
return QgsRectangle(self.startPoint, self.endPoint)
def deactivate(self):
super(ZoomInTool, self).deactivate()
self.deactivated.emit()
self.reset()
创建点shp矢量
def createPointShp(self, name_path, name):
'''创建点shp'''
fields = QgsFields()
fields.append(QgsField("类型", QVariant.String))
fields.append(QgsField("节点数", QVariant.String))
"""创建一个矢量文件编写器的实例,它将创建矢量文件
参数:
1. 新文件的路径(如果已存在则失败)
2. 属性编码
3. 字段映射
4. 几何类型 - WKBTYPE枚举
5. 图层的空间参考(QgsCoordinateReferenceSystem的实例) - 可选
6. 输出文件的驱动程序名称"""
writer = QgsVectorFileWriter(name_path, "GBK", fields, QgsWkbTypes.Point, driverName = "ESRI Shapefile") # GBK支持中文,UTF-8不支持中文
# 删除writer以将要素保存到磁盘
del writer
创建线shp矢量
def createLineShp(self, name_path, name):
'''创建线shp'''
fields = QgsFields()
fields.append(QgsField("类型", QVariant.String))
fields.append(QgsField("长度(m)", QVariant.String))
writer = QgsVectorFileWriter(name_path, "GBK", fields, QgsWkbTypes.LineString, driverName="ESRI Shapefile")
del writer
创建面shp矢量
def createPolygonShp(self, name_path, name):
'''创建面shp'''
fields = QgsFields()
fields.append(QgsField("类型", QVariant.String))
fields.append(QgsField("面积(m2)", QVariant.String))
writer = QgsVectorFileWriter(name_path, "GBK", fields, QgsWkbTypes.Polygon, driverName = "ESRI Shapefile")
del writer
点shp符号化(默认图形)
# self.shape:'circle'(圆形填充)self.color:QColor(255, 0, 255, 255)self.size:3
symbol = QgsMarkerSymbol.createSimple({'name': self.shape, 'color': self.color, 'size': self.size})
renderer = QgsSingleSymbolRenderer(symbol)
self.layer.setRenderer(renderer) # self.layer指需要符号化的图层
self.layer.triggerRepaint()
点shp符号化(svg填充)
svg = QgsSvgMarkerSymbolLayer(self.svgPath) # 加载SVG的路径
# svg.setSize(svg_size) # 设置大小
symbol = QgsMarkerSymbol()
symbol.appendSymbolLayer(svg) # 添加SVG的标记
symbol.deleteSymbolLayer(0) # 删除默认的原始标记
renderer = QgsSingleSymbolRenderer(symbol)
self.layer.setRenderer(renderer)
self.layer.triggerRepaint()
线shp符号化
symbol = QgsLineSymbol.createSimple({'color': 'red'}) # 'color': '0,128,0,255'
symbol.setColor(self.color) # 设置线颜色
symbol.setWidth(self.shp_width) # 设置线宽度
renderer = QgsSingleSymbolRenderer(symbol)
self.layer.setRenderer(renderer)
self.layer.triggerRepaint()
面shp符号化(图片填充)
image = QgsRasterFillSymbolLayer(self.fillImagePath)
symbol = QgsFillSymbol() # 填充符号
symbol.appendSymbolLayer(image)
symbol.setOpacity(0.5) # 设置填充图片透明度
symbol.setColor(QColor(2555,255,255,150))
# self.layer.renderer().symbol().symbolLayer(0).setStrokeStyle(Qt.SolidLine)
renderer = QgsSingleSymbolRenderer(symbol)
self.layer.setRenderer(renderer)
self.layer.triggerRepaint()
面shp符号化(纯色填充)
edge = QgsSimpleFillSymbolLayer()
edge.setStrokeStyle(self.strokeStyleList[0]) # 设置边框线型
edge.setStrokeColor(self.strokeStyleList[1]) # 设置边框颜色
edge.setStrokeWidth(self.strokeStyleList[2]) # 设置边框宽度
symbol = QgsFillSymbol()
symbol.changeSymbolLayer(0, edge)
symbol.setOpacity(0.5) # 设置填充透明度
symbol.setColor(self.fill_color)
renderer = QgsSingleSymbolRenderer(symbol)
self.layer.setRenderer(renderer)
self.layer.triggerRepaint()
为面图层添加一个新要素并设置要素属性信息
feature = QgsFeature(self.layer.fields()) # 为指定shp添加多边形要素
# self.points:QgsPointXY
feature.setGeometry(QgsGeometry.fromMultiPolygonXY([[self.points]]))
# 属性与图层属性表字段数量对应
feature.setAttributes(['aa', 'bb'])
(res, outFeatures) = self.layer.dataProvider().addFeatures([feature])
为线图层添加一个新要素并设置要素属性信息
feature = QgsFeature()
feature.setGeometry(QgsGeometry.fromMultiPolylineXY([self.points]))
feature.setAttributes(['aa', 'bb'])
(res, outFeatures) = self.layer.dataProvider().addFeatures([feature])
为点图层添加一个新要素并设置要素属性信息
feature = QgsFeature(self.layer.fields())
feature.setAttributes(['aa', 'bb'])
feature.setGeometry(QgsGeometry.fromPointXY(self.point))
(res, outFeatures) = self.layer.dataProvider().addFeatures([feature])
点、面文字标注
class DrawWordsLabel():
def __init__(self, mapCanvas, layer):
self.mapCanvas = mapCanvas
self.layer = layer
def defineLabels(self):
'''点、面文字标注'''
mark = QgsPalLayerSettings()
mark.drawLabels = True;
mark.fieldName = "aa" # 用self.layer的aa字段名标注
mark.centroidWhole = True # 设置位置参考的中心点
mark.placement= QgsPalLayerSettings.OverPoint
mark.yOffset = 3
format = QgsTextFormat()
format.setSize(10)
font = QFont()
font.setFamily("微软雅黑")
format.setFont(font)
format.setColor(QColor(255, 255, 0))
mark.setFormat(format)
self.layer.setLabeling(QgsVectorLayerSimpleLabeling(mark))
self.layer.setLabelsEnabled(True)
self.mapCanvas.refresh()
线文字注记
def drawingAnnotationText(self, point, words):
'''线文字标注(使用注记)'''
text_annotation = QgsTextAnnotation(self.mapCanvas)
# 设置注记填充符号
edge = QgsSimpleFillSymbolLayer()
edge.setStrokeStyle(Qt.DashLine) # 设置边框线型
edge.setStrokeColor(QColor(0, 0, 0, 0)) # 设置边框颜色(透明)
edge.setStrokeWidth(0.1) # 设置边框宽度
symbol = QgsFillSymbol()
symbol.changeSymbolLayer(0, edge)
symbol.setColor(QColor(0, 0, 0, 0)) # 填充颜色为透明
text_annotation.setFillSymbol(symbol)
# 设置点符号类型(透明)
markSymbol = QgsMarkerSymbol.createSimple({'name': 'circle', 'color': QColor(0, 0, 0, 0), 'outline_color': QColor(0, 0, 0, 0)})
text_annotation.setMarkerSymbol(markSymbol)
text_annotation.setMapPosition(point)
text_annotation.setFrameOffsetFromReferencePointMm(QPointF(0.1,0.1))
text_document = QTextDocument()
html_content = words
# #FFFF00:黄色 = QColor(255, 255, 0)
font_color, font_family, font_size = "#FFFF00", "微软雅黑", 13
text_document.setHtml('<font style="color:' + font_color +
"; font-family:" + font_family + "; font-size: " +
str(font_size) + 'px">' + html_content + "</font>")
text_annotation.setDocument(text_document)
# b = text_annotation.mapPosition()
text_annotation.setMapLayer(self.layer)
# text_annotation.setAssociatedFeature(feature)
# text_annotation.setVisible(isVisible)
QgsMapCanvasAnnotationItem(text_annotation, self.mapCanvas)
# mapCanvasAnnotationItem.annotation().setVisible(False)
# a = self.mapCanvas.scene().items()
# self.mapCanvas.scene().removeItem()
self.mapCanvas.refresh()
GDAL无损压缩压缩tif
def compressTif(self, orginImagePath, dstImagePath):
dataset = gdal.Open(orginImagePath)
driver = gdal.GetDriverByName('GTiff')
# strict=1表示和原来的影像严格一致,0表示可以有所调整
# callback为进度回调函数
# PACKBITS快速无损压缩,基于流
# LZW针对像素点,黑白图像效果好
driver.CreateCopy(dstImagePath, dataset, strict=1, options=["TILED=YES", "COMPRESS=LZW"])
del dataset
识别要素
class featureIdentifyTool(QgsMapToolIdentify):
resultSignal = pyqtSignal(list, list) # 定义一个信号用于接受两个list的数据
def __init__(self, mapCanvas):
super(featureIdentifyTool, self).__init__(mapCanvas)
self.mapCanvas = mapCanvas
self.rubberBand = QgsRubberBand(mapCanvas, True)
self.rubberBand.setColor(QColor(255, 0, 0, 100))
self.rubberBand.setWidth(1)
self.reset()
self.isPressed = False
def setLayers(self, layers):
'''初始化识别的图层'''
self.identifyLayers = layers
def reset(self):
'''重置'''
self.startPoint = self.endPoint = None
self.isPressed = False
self.rubberBand.reset(True)
def canvasReleaseEvent(self, e):
'''画布上鼠标松开事件,识别要素'''
self.isPressed = False
x = e.pos().x()
y = e.pos().y()
try: # 添加异常处理信息。防止识别其他图层时报错导致程序退出
results = self.identify(x, y, self.IdentifyMode.DefaultQgsSetting, self.identifyLayers, self.Type.VectorLayer)
except:
QMessageBox.information(QDialog(), '错误信息', '只能删除病害数据,请重新选择!')
return
resultLayers = []
resultFeatures = []
for identifyLayer in self.identifyLayers:
if identifyLayer.type() == QgsMapLayerType.VectorLayer:
identifyLayer.removeSelection()
features = []
resultFeatureIds = []
for result in results:
if result.mLayer.name() == identifyLayer.name():
feature = result.mFeature
resultFeatureIds.append(feature.id())
features.append(feature)
else:
continue
if len(resultFeatureIds) > 0:
identifyLayer.selectByIds(resultFeatureIds)
resultLayers.append(identifyLayer)
resultFeatures.append(features)
self.reset()
self.resultSignal.emit(resultLayers, resultFeatures) # 向信号提交信息
def deactivate(self):
super(featureIdentifyTool, self).deactivate()
self.deactivated.emit()
self.reset()
def actionIdentifyTriggered(self):
'''识别'''
self.mapTool = featureIdentifyTool(self.mapCanvas)
layers = PROJECT.mapLayers() # 获取所有图层(字典)
self.mapTool.setLayers(layers.values())
self.mapTool.resultSignal.connect(self.addIdentifyResultItem) # 信号
self.mapCanvas.setMapTool(self.mapTool)
def addIdentifyResultItem(self, layers, features):
'''要素信息框'''
for i in range(0, len(layers)):
# CustomMenuProvider.openAttributeDialog(self, layers[i])
for feature in features[i]:
infosTable = DiseaseInfosTable(feature) # 填写表头内容
infosTable.inputTableData()
class DiseaseInfosTable(QDialog, Ui_featureInTableDialog):
def __init__(self, feature):
super(DiseaseInfosTable, self).__init__()
self.setupUi(self)
self.feature = feature
def inputTableData(self):
'''设置属性表表头及表格数据'''
if self.feature.geometry().type() == QgsWkbTypes.PointGeometry: # 如果是点要素, 直接设置表头内容
self.tableWidget.setVerticalHeaderLabels(self.feature.fields().names())
count = 0
for attr in self.feature.attributes():
# 位置为第0行,第0列,后面为QTableWidgetItem对象,可以为str类型,int类型
self.tableWidget.setItem(count, 0, QTableWidgetItem(attr)) # 调用setTextAlignment()方法,设置文本居中显示
count = count + 1
elif self.feature.geometry().type() == QgsWkbTypes.LineGeometry: # 如果是线要素,增加一列再设置表头内容
orgin_row_num = self.tableWidget.rowCount()
cur_row_num = orgin_row_num + 1
self.tableWidget.setRowCount(cur_row_num) # 将当前的总行数加1
self.tableWidget.setVerticalHeaderLabels(self.feature.fields().names())
count = 0
for attr in self.feature.attributes():
self.tableWidget.setItem(count, 0, QTableWidgetItem(attr))
count = count+1
elif self.feature.geometry().type() == QgsWkbTypes.PolygonGeometry: # 如果是面要素,增加一列再设置表头内容
orgin_row_num = self.tableWidget.rowCount()
cur_row_num = orgin_row_num + 1
self.tableWidget.setRowCount(cur_row_num) # 将当前的总行数加1
self.tableWidget.setVerticalHeaderLabels(self.feature.fields().names())
count = 0
for attr in self.feature.attributes():
self.tableWidget.setItem(count, 0, QTableWidgetItem(attr))
count = count + 1
else:
return
self.show()
self.exec_() # show()与exec_()同时同时使用:窗口停靠,可弹出多个相同的窗体
选择要素并删除
def actionSelectAndDeleteFeatureTriggered(self):
'''选择要素并删除事件'''
self.mapTool = featureIdentifyTool(self.mapCanvas)
layers = PROJECT.mapLayers() # 获取所有图层(字典)
self.mapTool.setLayers(layers.values())
self.mapTool.resultSignal.connect(self.selectAndDeleteFeature) # 信号
self.mapCanvas.setMapTool(self.mapTool)
def selectAndDeleteFeature(self, layers, features):
'''选择要素并删除的接收信号'''
pos = {}
for item in self.mapCanvas.annotationItems():
annotationPosition = item.annotation().mapPosition()
pos[annotationPosition] = item
for i in range(0, len(layers)):
# layerPath = layers[i].source()
layerPath = layers[i].dataProvider().dataSourceUri();# 获取图层路径
for feature in features[i]:
if feature.geometry().type() == QgsWkbTypes.LineGeometry: # 如果是线要素则还需要删除注记
geom = feature.geometry()
ori_pts = []
if geom.isMultipart(): # "MultiPart"
for part in geom.parts():
pts = part.points()
for point in pts:
ori_pts.append(point)
else: # "Simple"
ori_pts = geom.get().points()
point = ori_pts[len(ori_pts) - 1] # 注记文字位置为线要素最后一个点的位置
pointXY = QgsPointXY(point.x(), point.y())
annotationItem = pos[pointXY]
annotationItem.annotation().setVisible(False)
layers[i].dataProvider().deleteFeatures([feature.id()]) # 如果是点、线、面要素均需要删除
取消当前地图工具
mapTool = self.mapCanvas.mapTool()
self.mapCanvas.unsetMapTool(mapTool) # 销毁当前地图工具
实时显示坐标
def showLngLat(self, point):
x = point.x()
y = point.y()
self.statusbar.showMessage(f'X:{x}, Y:{y}')
self.mapCanvas.xyCoordinates.connect(self.showLngLat)
标签:layer,self,feature,笔记,PyQGIS,mapCanvas,symbol,def
From: https://www.cnblogs.com/deng-notebook/p/18136435