3

In this topic https://gis.stackexchange.com/a/430301/192997 it is explained how to run a basic function from a canvas event :

Code edited by changing QgsMapTool by QgsMapToolPan:

def test(event):
    print('canvas release')

tool = QgsMapToolPan(iface.mapCanvas()) tool.canvasReleaseEvent = test iface.mapCanvas().setMapTool(tool)

I try to do the same to run a function from a plugin (made with PluginBuilder) with canvasReleaseEvent:

class MyPlugin:
    """QGIS Plugin Implementation."""
def __init__(self, iface):
    """Constructor."""

    self.iface = iface
    self.dlg = MyPluginDialog()

    #code......


def tr(self, message):

    #code......

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):

    #code......

def initGui(self):

    #code......


def unload(self):

    #code......


def run(self):

if self.first_start == True:
    self.first_start = False

# show the dialog
self.dlg.show()
# Run the dialog event loop
result = self.dlg.exec_()
# See if OK was pressed
if result:
    # Do something useful here - delete the line containing pass and
    # substitute with your code.
    pass

tool = QgsMapToolPan(self.iface.mapCanvas())
tool.canvasReleaseEvent = lambda event self.function_from_plugin(event)
self.iface.mapCanvas().setMapTool(tool)


def function_from_plugin(self, event):
    if self.dlg.horizontalSlider.value() == 1:
    ### rest of the code

but I get this error : AttributeError: 'QgsMapMouseEvent' object has no attribute 'dlg'

I looked other topics but I can't manage to understand everything:

How to link my QGIS plugin main class to mouse events from a custom Tool?

https://gis-ops.com/qgis-3-plugin-tutorial-pyqt-signal-slot-explained/

zakros
  • 347
  • 2
  • 8

1 Answers1

6

In your plugin script, you define tool in the main scope of the class. It means that tool runs every time QGIS loads the plugin. That means the plugin button will have no function.

You must define tool in run method to bind the tool to the button in the plugin toolbar. Because the plugin button runs run method.

You can use the following structure:

...

def function_from_plugin(self, event): if self.dlg.horizontalSlider.value() == 1: ### rest of the code

def run(self): tool = QgsMapTool(self.iface.mapCanvas()) tool.canvasReleaseEvent = lambda event: self.function_from_plugin(event) self.iface.mapCanvas().setMapTool(tool)

If your plugin is not very complex, I recommend using Minimal QGIS Plugin, instead of Plugin Builder, as follows. In this case, you just need __init__.py and metadata.txt.

from qgis.gui import QgsMapTool
from PyQt5.QtWidgets import QAction

def classFactory(iface): return MinimalPlugin(iface)

class MinimalPlugin: def init(self, iface): self.iface = iface

def initGui(self):
    self.action = QAction('Go!', self.iface.mainWindow())
    self.action.triggered.connect(self.run)
    self.iface.addToolBarIcon(self.action)

def unload(self):
    self.iface.removeToolBarIcon(self.action)
    del self.action

def function_from_plugin(self, event):
    print("canvas released")

def run(self):
    tool = QgsMapTool(self.iface.mapCanvas())
    tool.canvasReleaseEvent = lambda event: self.function_from_plugin(event)
    self.iface.mapCanvas().setMapTool(tool)

Kadir Şahbaz
  • 76,800
  • 56
  • 247
  • 389
  • Thank you for answering my question Kadir. I think I have not well built my plugin... Is it compulsory to write the plugin functions in def run(self) ? I did another way (see my edit) – zakros Oct 12 '22 at 15:32
  • if self.dlg.horizontalSlider.value() == 1: ### rest of the code def run(self): tool = QgsMapTool(self.iface.mapCanvas()) tool.canvasReleaseEvent = lambda event: self.function_from_plugin(event) self.iface.mapCanvas().setMapTool(tool)``` Unfortunately nothings occurs when I insert this lines in my plugin script :( – zakros Oct 13 '22 at 13:48
  • 1
    Please add the whole structure of your last script to the question body so that we can check what is wrong. Comment area is not appropriate for codes as you see. – Kadir Şahbaz Oct 14 '22 at 08:19
  • Understood Kadir, I edited the code in the topic – zakros Oct 14 '22 at 09:18
  • Sorry my mistake, your solution is working. It is just not working with QgsMapToolPan, do you know why ? – zakros Oct 17 '22 at 16:19