En el post anterior se produjo un plugin plantilla tipo botón checkeable para PyQGIS 3. Ahora lo vamos a adaptar para producir rectángulos por dragado del Map Canvas; tal como se realizó en este otro post. A continuación, para tener una plantilla verdadera, se elimina en template.py todo el código que permitía generar las tooltips consideradas en el post anterior y se reserva para tal fin. El código final se presenta a continuación.
""" /*************************************************************************** Test A QGIS plugin Plugin for testing things ------------------- begin : 2015-01-28 copyright : (C) 2015-2017 by German Carrillo, GeoTux email : gcarrillo@linuxmail.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ """ import os # Import the PyQt and QGIS libraries from qgis.core import QgsApplication, QgsRasterLayer, QgsRaster from qgis.gui import QgsMapToolEmitPoint from PyQt5.QtCore import QObject, QTimer, Qt from PyQt5.QtWidgets import ( QMessageBox, QAction, QMenu, QActionGroup, QWidgetAction, QToolTip) from PyQt5.QtGui import ( QIcon ) class Test: def __init__(self, iface): # Save reference to the QGIS interface self.iface = iface self.tooltipRaster = TooltipRasterMapTool( self.iface ) def initGui(self): # Create action that will start plugin configuration self.action = QAction( QIcon( os.path.dirname(os.path.realpath(__file__)) + "/icon_default.png" ), "Tooltip for Raster Values", self.iface.mainWindow() ) # connect the action to the run method self.action.triggered.connect( self.run ) self.action.setCheckable( True ) self.iface.mapCanvas().mapToolSet.connect( self.mapToolWasSet ) # Add toolbar button to the Plugins toolbar self.iface.addToolBarIcon(self.action) # Add menu item to the Plugins menu self.iface.addPluginToMenu("&Tooltip for Raster Values", self.action) def unload(self): # Remove the plugin menu item and icon self.iface.removePluginMenu( "&Tooltip for Raster Values", self.action ) self.iface.removeToolBarIcon(self.action) # run method that performs all the real work def run(self, checked): if checked: self.iface.mapCanvas().setMapTool( self.tooltipRaster ) else: self.iface.mapCanvas().unsetMapTool( self.tooltipRaster ) def mapToolWasSet( self, newTool ): if type(newTool) != TooltipRasterMapTool: self.action.setChecked( False ) class TooltipRasterMapTool(QgsMapToolEmitPoint): def __init__(self, iface): self.iface = iface self.canvas = self.iface.mapCanvas() QgsMapToolEmitPoint.__init__(self, self.canvas) def canvasPressEvent(self, e): pass def canvasReleaseEvent(self, e): pass def canvasMoveEvent(self, e): pass
El código total adaptado en template.py se presenta a continuación. Sin embargo, para que funcione adecuadamente se requieren otras modificaciones que se detallan más adelante.
""" /*************************************************************************** Test A QGIS plugin Plugin for testing things ------------------- begin : 2015-01-28 copyright : (C) 2015-2017 by German Carrillo, GeoTux email : gcarrillo@linuxmail.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ """ import os # Import the PyQt and QGIS libraries from qgis.core import (QgsApplication, QgsRasterLayer, QgsRaster, QgsPointXY, QgsGeometry, QgsRectangle, QgsProject, QgsVectorLayer, QgsFeature) from qgis.gui import QgsMapToolEmitPoint, QgsRubberBand from PyQt5.QtCore import QObject, QTimer, Qt from PyQt5.QtWidgets import ( QMessageBox, QAction, QMenu, QActionGroup, QWidgetAction, QToolTip) from PyQt5.QtGui import ( QIcon ) class Test: def __init__(self, iface): # Save reference to the QGIS interface self.iface = iface self.tooltipRaster = TooltipRasterMapTool( self.iface ) def initGui(self): # Create action that will start plugin configuration self.action = QAction( QIcon( os.path.dirname(os.path.realpath(__file__)) + "/icon_default.png" ), "For Making Rectangles", self.iface.mainWindow() ) # connect the action to the run method self.action.triggered.connect( self.run ) self.action.setCheckable( True ) self.iface.mapCanvas().mapToolSet.connect( self.mapToolWasSet ) # Add toolbar button to the Plugins toolbar self.iface.addToolBarIcon(self.action) # Add menu item to the Plugins menu self.iface.addPluginToMenu("&Tooltip for Raster Values", self.action) def unload(self): # Remove the plugin menu item and icon self.iface.removePluginMenu( "&Tooltip for Raster Values", self.action ) self.iface.removeToolBarIcon(self.action) # run method that performs all the real work def run(self, checked): if checked: self.iface.mapCanvas().setMapTool( self.tooltipRaster ) else: self.iface.mapCanvas().unsetMapTool( self.tooltipRaster ) def mapToolWasSet( self, newTool ): if type(newTool) != TooltipRasterMapTool: self.action.setChecked( False ) class TooltipRasterMapTool(QgsMapToolEmitPoint): def __init__(self, iface): self.iface = iface self.canvas = self.iface.mapCanvas() QgsMapToolEmitPoint.__init__(self, self.canvas) self.start_point = None self.end_point = None self.rubber_band = QgsRubberBand(self.canvas, True) self.rubber_band.setColor(Qt.red) self.rubber_band.setOpacity(0.7) def canvasPressEvent(self, e): self.start_point = self.toMapCoordinates(e.pos()) self.end_point = self.start_point def canvasReleaseEvent(self, e): self.end_point = self.toMapCoordinates(e.pos()) r = self.get_rectangle() self.rubber_band.reset() self.start_point = None self.end_point = None rect_feat = r.asWktPolygon() #definng Status Bar statusBar = self.iface.mainWindow().statusBar() #selecting elements in Status Bar elements = statusBar.children() #selecting widget in Status Bar with ESPG EPSG = elements[1].children()[10] EPSG = EPSG.text().split(':') uri = "Polygon?crs=epsg:" + EPSG[1] + "&field=id:integer""&index=yes" mem_layer = QgsVectorLayer(uri, 'rectangle', 'memory') prov = mem_layer.dataProvider() feat = QgsFeature() feat.setAttributes([0]) feat.setGeometry(QgsGeometry.fromWkt(rect_feat)) prov.addFeatures([feat]) QgsProject.instance().addMapLayer(mem_layer) def get_rect_points(self, startPoint, endPoint): points = [[QgsPointXY(startPoint.x(), startPoint.y()), QgsPointXY(endPoint.x(), startPoint.y()), QgsPointXY(endPoint.x(), endPoint.y()), QgsPointXY(startPoint.x(), endPoint.y())]] return points def get_rectangle(self): rect = QgsRectangle(self.start_point, self.end_point) return rect def canvasMoveEvent(self, e): if self.start_point: end_point = self.toMapCoordinates(e.pos()) self.rubber_band.reset() p = self.get_rect_points(self.start_point, end_point) self.rubber_band.setToGeometry(QgsGeometry.fromPolygonXY(p), None)
La carpeta completa de la plantilla (template) se guarda con el nombre de makingrectangle en la ruta de plugins de QGIS 3. El archivo template.py que tiene el código anterior se renombra como making_rectangles.py. Para que lo procese de la manera esperada se hace la modificación siguiente en el __init__py.
. . . def classFactory(iface): # load Test class from file test.py from .making_rectangles import Test return Test(iface)
También necesitamos la modificación siguiente en el metadata.txt para que el nombre del plugin sea procesado como se espera. Una modificación similar también fue realizada en el código fuente al inicio del método 'initGui'.
; the next section is mandatory [general] name=Making Rectangles plugin description=For Making Rectangles. . .
Finalmente, se produce un icono personalizado (con el mismo nombre) para identificarlo de manera precisa. La ejecución del plugin se observa en la imagen a continuación.
No hay comentarios:
Publicar un comentario