Сделал плагин для Qgis, который бы считал сумму определенного показателя выбранных объектов. Логика была такова, что просчет начинался, когда пользователь нажимает на кнопку (здесь объект называется sumButton) и выводит значение в виде объекта label. Но расчет суммы начинается не тогда, когда я нажимаю кнопку, а при запуске плагина, сама кнопка не работает, соответственно, чтобы посчитать сумму других объектов, надо плагин закрыть и открыть снова.
При запуске в журнале выдается следующее сообщение:
2024-03-03T21:53:19 WARNING Traceback (most recent call last):
File "C:\Users/d.arhipov/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\sumarea\SumArea.py", line 254, in run
self.dockwidget.sumButton.clicked.connect(self.select_features())
TypeError: argument 1 has unexpected type 'NoneType'
from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication, Qt
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QAction
# Initialize Qt resources from file resources.py
from .resources import *
from qgis.PyQt.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from qgis.PyQt.QtSql import QSqlDatabase, QSqlQuery
from PyQt5.QtWidgets import QTableView, QApplication
from urllib.request import urlopen
from qgis.core import *
from qgis.gui import *
from qgis.gui import QgsMapToolEmitPoint
from qgis.utils import iface
from qgis.gui import QgsMapTool
# Import the code for the DockWidget
from .SumArea_dockwidget import SumAreaDockWidget
import os.path
class SumArea:
"""QGIS Plugin Implementation."""
def __init__(self, iface):
"""Constructor.
:param iface: An interface instance that will be passed to this class
which provides the hook by which you can manipulate the QGIS
application at run time.
:type iface: QgsInterface
"""
# Save reference to the QGIS interface
self.iface = iface
# initialize plugin directory
self.plugin_dir = os.path.dirname(__file__)
# initialize locale
locale = QSettings().value('locale/userLocale')[0:2]
locale_path = os.path.join(
self.plugin_dir,
'i18n',
'SumArea_{}.qm'.format(locale))
if os.path.exists(locale_path):
self.translator = QTranslator()
self.translator.load(locale_path)
QCoreApplication.installTranslator(self.translator)
# Declare instance attributes
self.actions = []
self.menu = self.tr(u'&SumArea')
# TODO: We are going to let the user set this up in a future iteration
self.toolbar = self.iface.addToolBar(u'SumArea')
self.toolbar.setObjectName(u'SumArea')
#print "** INITIALIZING SumArea"
self.pluginIsActive = False
self.dockwidget = None
# noinspection PyMethodMayBeStatic
def tr(self, message):
"""Get the translation for a string using Qt translation API.
We implement this ourselves since we do not inherit QObject.
:param message: String for translation.
:type message: str, QString
:returns: Translated version of message.
:rtype: QString
"""
# noinspection PyTypeChecker,PyArgumentList,PyCallByClass
return QCoreApplication.translate('SumArea', message)
def add_action(
self,
icon_path,
text,
callback,
enabled_flag=True,
add_to_menu=True,
add_to_toolbar=True,
status_tip=None,
whats_this=None,
parent=None):
"""Add a toolbar icon to the toolbar.
:param icon_path: Path to the icon for this action. Can be a resource
path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
:type icon_path: str
:param text: Text that should be shown in menu items for this action.
:type text: str
:param callback: Function to be called when the action is triggered.
:type callback: function
:param enabled_flag: A flag indicating if the action should be enabled
by default. Defaults to True.
:type enabled_flag: bool
:param add_to_menu: Flag indicating whether the action should also
be added to the menu. Defaults to True.
:type add_to_menu: bool
:param add_to_toolbar: Flag indicating whether the action should also
be added to the toolbar. Defaults to True.
:type add_to_toolbar: bool
:param status_tip: Optional text to show in a popup when mouse pointer
hovers over the action.
:type status_tip: str
:param parent: Parent widget for the new action. Defaults None.
:type parent: QWidget
:param whats_this: Optional text to show in the status bar when the
mouse pointer hovers over the action.
:returns: The action that was created. Note that the action is also
added to self.actions list.
:rtype: QAction
"""
icon = QIcon(icon_path)
action = QAction(icon, text, parent)
action.triggered.connect(callback)
action.setEnabled(enabled_flag)
if status_tip is not None:
action.setStatusTip(status_tip)
if whats_this is not None:
action.setWhatsThis(whats_this)
if add_to_toolbar:
self.toolbar.addAction(action)
if add_to_menu:
self.iface.addPluginToMenu(
self.menu,
action)
self.actions.append(action)
return action
def initGui(self):
"""Create the menu entries and toolbar icons inside the QGIS GUI."""
icon_path = ':/plugins/SumArea/icon.png'
self.add_action(
icon_path,
text=self.tr(u''),
callback=self.run,
parent=self.iface.mainWindow())
def select_features(self):
layer = self.iface.activeLayer()
features = layer.selectedFeatures()
area = sum([f.attributes()[5] for f in features])
self.dockwidget.label.setText(str(area))
print(area)
#--------------------------------------------------------------------------
def onClosePlugin(self):
"""Cleanup necessary items here when plugin dockwidget is closed"""
#print "** CLOSING SumArea"
# disconnects
self.dockwidget.closingPlugin.disconnect(self.onClosePlugin)
# remove this statement if dockwidget is to remain
# for reuse if plugin is reopened
# Commented next statement since it causes QGIS crashe
# when closing the docked window:
# self.dockwidget = None
self.pluginIsActive = False
def unload(self):
"""Removes the plugin menu item and icon from QGIS GUI."""
#print "** UNLOAD SumArea"
for action in self.actions:
self.iface.removePluginMenu(
self.tr(u'&SumArea'),
action)
self.iface.removeToolBarIcon(action)
# remove the toolbar
del self.toolbar
#--------------------------------------------------------------------------
def run(self):
"""Run method that loads and starts the plugin"""
if not self.pluginIsActive:
self.pluginIsActive = True
#print "** STARTING SumArea"
# dockwidget may not exist if:
# first run of plugin
# removed on close (see self.onClosePlugin method)
if self.dockwidget == None:
# Create the dockwidget (after translation) and keep reference
self.dockwidget = SumAreaDockWidget()
# connect to provide cleanup on closing of dockwidget
self.dockwidget.closingPlugin.connect(self.onClosePlugin)
# show the dockwidget
# TODO: fix to allow choice of dock location
self.iface.addDockWidget(Qt.TopDockWidgetArea, self.dockwidget)
self.dockwidget.show()
self.dockwidget.sumButton.clicked.connect(self.select_features())