I don't have enough reputation to reply to @ekhumoro, but wanted to add to their answer with an applied answer specific to MouseEvents for those who might benefit, based on a similar issue I was having.
Scenario
Display an image in the central widget, and connect a custom signal to capture mouse double click actions in the central widget.
Source for test image: https://en.wikipedia.org/wiki/Standard_test_image#/media/File:SIPI_Jelly_Beans_4.1.07.tiff
Consider the following:
A basic QMainWindow class which loads a supplied image_file
and shows the image in a custom sub-class of the QLabel
class, fit to the window:
import sys
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QPixmap, QImage, QPalette, QMouseEvent
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QScrollArea)
class ImageView(QMainWindow):
def __init__(self):
super().__init__()
self.initializeUI()
self.image = QImage()
def initializeUI(self):
self.setMinimumSize(300, 200)
self.setWindowTitle("Image Viewer")
# self.showMaximized()
self.createMainQLabel()
self.show()
def createMainQLabel(self):
"""Create an instance of the imageQLabel class and set it
as the main window's central widget."""
self.image_qlabel = imageQLabel(self)
self.image_qlabel.resize(self.image_qlabel.pixmap().size())
self.scroll_area = QScrollArea()
self.scroll_area.setBackgroundRole(QPalette.Dark)
self.scroll_area.setAlignment(Qt.AlignCenter)
self.scroll_area.setWidget(self.image_qlabel)
self.setCentralWidget(self.scroll_area)
class imageQLabel(QLabel):
"""Subclass of QLabel for displaying image"""
def __init__(self, parent, image_file="images/SIPI_Jelly_Beans_4.1.07.tiff"):
super().__init__(parent)
self.openImage(image_file)
self.setScaledContents(True)
self.setAlignment(Qt.AlignCenter)
def openImage(self, image_file):
# Get image, create the pixmap and resize to fit window
self.image = QImage(image_file)
self.setPixmap(QPixmap().fromImage(self.image))
self.resize(self.pixmap().size())
"""
Other methods used to customize the class, for example:
- Resize
- Rotate
- Crop
- ...
...
"""
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setAttribute(Qt.AA_DontShowIconsInMenus, True)
window = ImageView()
sys.exit(app.exec_())
When executed, yield a simple window with the image:
SIPI Test Image shown in PyQT5 Window
What we would like to do is add a mouseDoubleClickEvent
to the imageQLabel
sub-class, but ensure that other widgets or classes in the program can access the event signals. To do this, you can modify @ekhumoro's answer #2 to accommodate a pyqtSignal
.
First, add the signal to the attributes of the imageQLabel
class. Here, we need the full QMouseEvent
rather than just an int
:
import sys
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QPixmap, QImage, QPalette, QMouseEvent
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QScrollArea)
class imageQLabel(QLabel):
"""Subclass of QLabel for displaying image"""
# Class attributes
mouseDoubleClickSignal = pyqtSignal(QMouseEvent)
We wish to pass the event from that pyqtSignal
to some other method in our ImageView
main window class. As an example, let's make a method to print the cursor position when the user double clicks in the imageQLabel
sub-class.
In ImageView
:
class ImageView(QMainWindow):
"""
...
The rest of the class code
...
"""
def print_mouse(self, event):
print("print_mouse event from QMainWindow: {}".format((event.x(), event.y())))
Now we just need to connect print_mouse
to the custom pyqtSignal
we made. It makes the most sense to do this in the initializeUI
method:
def initializeUI(self):
self.setMinimumSize(300, 200)
self.setWindowTitle("Image Viewer")
# self.showMaximized()
self.createMainQLabel()
# Connect the signal from custom imageQLabel class
# to the QMainWindow
self.image_qlabel.mouseDoubleClickSignal.connect(self.print_mouse)
self.show()
These modifications now print the cursor position when double clicking inside of the imageQLabel
sub-class in the central widget. The call to print_mouse
is outside of the sub-class. Moreover, double-clicking outside of the central widget (like outside of the frame of the image) does not call print_mouse
because the mouseDoubleClickEvent
is only active for the central widget.
%user profile%\AppData\Local\Programs\Python\Python39\python.exe
%script path%\stackoverflowsolution.py
print_mouse event from QMainWindow: (115, 140)
print_mouse event from QMainWindow: (54, 55)