Search code examples
pythonpyqt5qlabelqpixmap

`QPixmap` and `QLabel` size slightly increases when reloading


When I'm trying to make my app, I stumbled upon this unexpected behavior where when I re-display a new QPixmap in a QLabel. I tried to simplify the code and ended up with the code below. I also attached the video of the behavior.

enter image description here

I provided here a replicable example (It just needs some .jpg file in the same directory):

import sys
import os
import random

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel, QSizePolicy
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap

class AppDemo(QWidget):
    def __init__(self):
        super().__init__()
        
        self.setGeometry(200, 200, 400, 400)
        current_working_dir = os.path.abspath('')
        dir_files = os.listdir(current_working_dir)

        # Saving .jpg from the dir
        self.picture = []
        for file in dir_files:
            if file.endswith(".jpg"):
                self.picture.append(file)
        
        self.label = QLabel()
        self.label.setStyleSheet("border: 1px solid black;")  # <- for the debugging
        self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding)
        
        self.label.setPixmap(self.random_picture_selector())

        button = QPushButton("Reload Picture")
        button.clicked.connect(self.reload_picture)

        layout = QVBoxLayout(self)
        layout.addWidget(button)
        layout.addWidget(self.label)

    def reload_picture(self):
        self.label.setPixmap(self.random_picture_selector())

    def random_picture_selector(self):
        rnd_picture = random.choice(self.picture)
        pixmap = QPixmap(rnd_picture)
        pixmap = pixmap.scaledToWidth(self.label.width(), Qt.SmoothTransformation)
        # pixmap = pixmap.scaled(self.label.width(), self.label.height(), Qt.KeepAspectRatio) # <- even this is not working
        return pixmap

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = AppDemo()
    demo.show()
    sys.exit(app.exec_())

Additional Infos:

When simplifying the code I realized that the problem disappears when I removed these following lines. (although I'm not very sure that these part of the code really causes the problem)

        pixmap = pixmap.scaledToWidth(self.label.width(), Qt.SmoothTransformation)
        # pixmap = pixmap.scaled(self.label.width(), self.label.height(), Qt.KeepAspectRatio) # <- even this is not working

I really have no idea what causes the problem even after looking for the Docs of QPixmap and QLabel.


Solution

  • The problem is caused by the stylesheet border. If you just print the pixmap and label size after setting the pixmap, you'll see that the label width is increased by 2 pixels, which is the sum of the left and right border.

    You either remove the border, or you use the contentsRect():

    width = self.label.contentsRect().width()
    pixmap = pixmap.scaledToWidth(width, Qt.SmoothTransformation)
    

    Read more about the Box Model in the Qt style sheet documentation.