Dynamic Image Scaling Widget
-
I want to create a widget that resizes the image to fit completely within it's boundaries, keeping aspect ratio.
This is what I am trying.It seems that the resize event is called infinitely, even if I do not actually resize the window. The widget just keeps scaling on its own. Is there a proper solution for creating a scalable image?
class ScalableImageLabel(QLabel): def __init__(self, icon: QIcon, parent=None): super().__init__(parent) self.setFrameStyle(QFrame.StyledPanel | QFrame.Plain) self.setLineWidth(1) self.__icon: QIcon = icon self.__pixmap = self.__icon.pixmap(self.size()) self.setPixmap(self.__pixmap) self.setAlignment(Qt.AlignCenter) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) def sizeHint(self): if self.__pixmap and not self.__pixmap.isNull(): return self.__pixmap.size() return super().sizeHint() def resizeEvent(self, event): self.__pixmap = self.__icon.pixmap(self.size()) self.setPixmap(self.__pixmap) super().resizeEvent(event)
This is my grid layout
class GridView: __COLUMNS = 5 def __init__(self, paths: [str]): self.__layout: QGridLayout = QGridLayout() row_index: int = 0 col_index: int = 0 for path in paths: self.__layout.addWidget(ScalableImageLabel(QIcon(path)), row_index, col_index) col_index += 1 if col_index >= self.__COLUMNS: col_index = 0 row_index += 1 def get_grid(self) -> QGridLayout: return self.__layout class MainWindow(QMainWindow): def __init__(self): super().__init__() self.title = "Test" self.setWindowTitle(self.title) win = QWidget(self) paths = ["image1.png", "image2.png", "image3.png", "image4.png", "image5.png"] grid = GridView(paths).get_grid() win.setLayout(grid) self.setCentralWidget(win)
I've tried using directly the paint event as well but it is incredibly slow, even for 20 images on display.
-
@andrei_cp said in Dynamic Image Scaling Widget:
It seems that the resize event is called infinitely, even if I do not actually resize the window. The widget just keeps scaling on its own.
Print out what the size was and is now in
resizeEvent()
. Does it remain the same? Does it grow/shrink continuously? Does it maybe toggle between bigger and smaller? You may need to save the old size or look at the current size --- of the widget or the bitmap --- and if it remains the same or only differs by a tiny amount perhaps you need to not resize again at that point? -
Have you tried QLabel.setScaledContents(), see https://doc.qt.io/qt-6/qlabel.html#scaledContents-prop ?
-
@JonB Yes. I print the size, and it seems it grows constantly. If I resize the window once, it will just keep resizing forever. Even if I do make a change to not resize if there isn't a big difference between old and new size, the function still seems to be called infinitely and I don't understand why. Shouldn't the resize be called once for every element? There seems to be a recursive call somewhere.
-
@andrei_cp
Maybe your resetting the pixmap to a new size inresizeEvent()
in turn causes a new size event, and a bit bigger than before? That is the recursion.
In any case I imagine you want to use @friedemannkleint's suggestion, then you only need the label to resize, see if that helps.