2

I have a QMainWindow containing a child QWidget containing itself a QLabel.

When the window is maximized (e.g. by clicking the maximize icon on the window), the QLabel.resizeEvent() handler is called multiple times (supposedly to follow the progressive enlargement of the window until it takes the full desktop space).

The code in the event handler calls setPixmap() to scale the label pixmap. This is a relatively long operation which slows the process. Code for the label:

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QLabel, QFrame, QGridLayout
from PyQt5.QtGui import QImageReader, QPixmap

class DisplayArea(QLabel):
    def __init__(self):
        super().__init__()
        self.pix_map = None
        self.init_ui()

    def init_ui(self):
        self.setMinimumSize(1, 1)
        self.setStyleSheet("border:1px solid black;")

    def set_image(self, image):
        self.pix_map = QPixmap.fromImage(image)
        self.scale_image(self.size())

    def scale_image(self, size):
        if self.pix_map is None:
            return

        scaled = self.pix_map.scaled(size, Qt.KeepAspectRatio)
        self.setPixmap(scaled)

    def resizeEvent(self, e):
        self.scale_image(e.size())
        super().resizeEvent(e)

Is there a possibility to process the event only once, when the window has reached its final size?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
mins
  • 6,478
  • 12
  • 56
  • 75
  • The question is: how to know that size no longer change at least for a certain period of time? – eyllanesc Dec 29 '18 at 20:52
  • @eyllanesc: My need is to scale the label pixmap when the window is resized, but I discovered this strange effect when the window is maximized. During a manual resizing, the handler is called fewer times, it's ok. So yes your rephrasing is correct. – mins Dec 29 '18 at 21:15
  • How many times is it called when it is maximized and how often? In my case(Linux, PyQt5 5.11.3) I do not observe what you point out to me but I have an idea, but its operation depends on the data I ask – eyllanesc Dec 29 '18 at 21:19
  • @eyllanesc: 160 times for a single click on maximize. – mins Dec 29 '18 at 21:23
  • and how often does the maximized average take? – eyllanesc Dec 29 '18 at 21:24
  • @eyllanesc: I'd say it takes 0.8s for the 160 calls. – mins Dec 29 '18 at 21:35
  • okay, with my idea I'll just call it 8 times, my initial version had a problem, try the current version – eyllanesc Dec 29 '18 at 21:50

1 Answers1

1

The problem is that the resizeEvent is called many times in the time that the window is maximized, and that same number of times is what you call scale_image. One possible possible is not to update unless a period of time passes. In the following example only resizes for times greater than 100 ms (the time you must calibrate):

from PyQt5 import QtCore, QtGui, QtWidgets

class DisplayArea(QtWidgets.QLabel):
    def __init__(self):
        super().__init__()
        self.pix_map = QtGui.QPixmap()
        self._flag = False
        self.init_ui()

    def init_ui(self):
        self.setMinimumSize(1, 1)
        self.setStyleSheet("border:1px solid black;")

    def set_image(self, image):
        self.pix_map = QtGui.QPixmap.fromImage(image)
        self.scale_image()

    def scale_image(self):
        if self.pix_map.isNull():
            return
        scaled = self.pix_map.scaled(self.size(), QtCore.Qt.KeepAspectRatio)
        self.setPixmap(scaled)

    def resizeEvent(self, e):
        if not self._flag:
            self._flag = True
            self.scale_image()
            QtCore.QTimer.singleShot(100, lambda: setattr(self, "_flag", False))
        super().resizeEvent(e)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = QtWidgets.QMainWindow()
    da = DisplayArea()
    da.set_image(QtGui.QImage("logo.png"))
    w.setCentralWidget(da)
    w.show()
    sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241