3

I'm trying to capture MouseClick events on the QgsMapCanvas. The goal is to intercept the right mouse button and display a custom context menu. If the right mouse button is pressed with a modifier key (SHIFT+CTRL for example), the active tool action should be triggered.

I tried to install an event filter on the QgsMapCanvas provided by the iface, but this is not working.

class MyPlugin:
    def __init__(self, iface: QgisInterface):
        self.iface = iface
        self.eventFilter: MyEventFilter = None

    def initGui(self):
        self.registerEventFilter()

    def unload(self):
        self.unregisterEventFilter()

    def registerEventFilter(self):
        if not self.eventFilter:
            self.eventFilter = MyEventFilter(self.iface.mapCanvas())
        self.iface.mapCanvas().installEventFilter(self.eventFilter)

    def unregisterEventFilter(self):
        if self.eventFilter:
            self.eventFilter.deleteLater()
            self.eventFilter = None

and the EventHandler looks like this:

class MyEventFilter(QObject):

    def __init__(self, parent: Optional[QObject] = None) -> None:
        super().__init__(parent)

    def eventFilter(self, caller: QObject, event: QEvent) -> bool:
        if event.type() == QEvent.MouseButtonRelease:
            QMessageBox.information(None, 'MyEventFilter', f'event: {event}')
            return True
        return False

But when I click, nothing happens. I guess the active tool itself is already filtering the click?

I've seen that QgsMapCanvas has signals for the mouse position as well as keypresses, but unfortunately no mouse click signals.

I know that you can implement a map tool, but the idea is to have a global contextmenu handler that is always called first. Only with a modifier key the original tool action should be triggered.

Is there any mechanism to achieve this?

1

You need to install the event filter on the canvas' viewport. Event filters do not work as expected with mouse events on classes derived from QAbstractScrollArea (QgsMapCanvas, QGraphicsView, QTextEdit, etc...)

Replace your code with the following, and it should work.

class MyPlugin:
    def __init__(self, iface: QgisInterface):
        self.iface = iface
        self.eventFilter: MyEventFilter = None

    def initGui(self):
        self.registerEventFilter()

    def unload(self):
        self.unregisterEventFilter()

    def registerEventFilter(self):
        if not self.eventFilter:
            self.eventFilter = MyEventFilter(self.iface.mapCanvas())
        self.iface.mapCanvas().viewport().installEventFilter(self.eventFilter)

    def unregisterEventFilter(self):
        if self.eventFilter:
            self.iface.mapCanvas().viewport().removeEventFilter(self.eventFilter)
            self.eventFilter.deleteLater()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.