PyQT playground: image gallery with zoom
Posted by Marco Dinacci on 0 commentsIn this article I'm going to create a small PyQT based application that displays images in a grid and that zoom the image hovered by the mouse.
This is how the final application looks like:

The first class we need is an ImageGallery, which is a mere QDialog using a QGridLayout.
class ImageGallery(QDialog):
def __init__(self, parent=None):
super(QDialog, self).__init__(parent)
self.setWindowTitle("Image Gallery")
self.setLayout(QGridLayout(self))
def populate(self, pics, size, imagesPerRow=4,
flags=Qt.KeepAspectRatioByExpanding):
row = col = 0
for pic in pics:
label = ImageLabel("")
pixmap = QPixmap(pic)
pixmap = pixmap.scaled(size, flags)
label.setPixmap(pixmap)
self.layout().addWidget(label, row, col)
col +=1
if col % imagesPerRow == 0:
row += 1
col = 0
The code is very simple, the class has only one public method, populate, which iterates over the images passed in the argument pics, create a QPixmap for each of them, and add them to the layout.
The interesting bit is the line where I create the label:
label = ImageLabel("")
This line creates a new instance of the ImageLabel, which is listed here below:
class ImageLabel(QLabel):
""" This widget displays an ImagePopup when the mouse enters its region """
def enterEvent(self, event):
self.p = ImagePopup(self)
self.p.show()
event.accept()
The ImageLabel is a normal QLabel except that I redefined the enterEvent in order to show an ImagePopup when the mouse enters the label.
Finally, the ImagePopup class, responsible for the creation of the zoomed popup image.
class ImagePopup(QLabel):
"""
The ImagePopup class is a QLabel that displays a popup, zoomed image
on top of another label.
"""
def __init__(self, parent):
super(QLabel, self).__init__(parent)
# set pixmap and size, which is the double of the original pixmap
thumb = parent.pixmap()
imageSize = thumb.size()
imageSize.setWidth(imageSize.width()*2)
imageSize.setHeight(imageSize.height()*2)
self.setPixmap(thumb.scaled(imageSize,Qt.KeepAspectRatioByExpanding))
# center the zoomed image on the thumb
position = self.cursor().pos()
position.setX(position.x() - thumb.size().width())
position.setY(position.y() - thumb.size().height())
self.move(position)
# FramelessWindowHint may not work on some window managers on Linux
# so I force also the flag X11BypassWindowManagerHint
self.setWindowFlags(Qt.Popup | Qt.WindowStaysOnTopHint
| Qt.FramelessWindowHint
| Qt.X11BypassWindowManagerHint)
def leaveEvent(self, event):
""" When the mouse leave this widget, destroy it. """
self.destroy()
That's it, it's very simple as you can see. You can download the python code or a zip file containing the code and the images.
Thanks for reading.