Skip to content Skip to sidebar Skip to footer

Resizing A Window With Pyqt5 - How Do I Reduce The Size Of A Widget To Allow The Window To Be Shrunk?

I'm trying to learn it by re-making an old command line C program I've got for working with pixel art. At the moment, the main window starts as a single QLabel set to show a 300 x

Solution 1:

While the OP proposed solution might work, it has an important drawback: it uses a QScrollArea for the wrong purpose (since it's never used for scrolling). That approach creates unnecessary overhead while resizing, as the view will need to compute lots of things about its contents before "finishing" the resize event (including scroll bar ranges and geometries) that, in the end, will never be actually used.

The main problem comes from the fact that QLabel doesn't allow resizing to a size smaller than the original pixmap set. To work around this issue, the simplest solution is to create a custom QWidget subclass that draws the pixmap on its own.

classImageViewer(QWidget):
    pixmap = None
    _sizeHint = QSize()
    ratio = Qt.KeepAspectRatio
    transformation = Qt.SmoothTransformation

    def__init__(self, pixmap=None):
        super().__init__()
        self.setPixmap(pixmap)

    defsetPixmap(self, pixmap):
        if self.pixmap != pixmap:
            self.pixmap = pixmap
            ifisinstance(pixmap, QPixmap):
                self._sizeHint = pixmap.size()
            else:
                self._sizeHint = QSize()
            self.updateGeometry()
            self.updateScaled()

    defsetAspectRatio(self, ratio):
        if self.ratio != ratio:
            self.ratio = ratio
            self.updateScaled()

    defsetTransformation(self, transformation):
        if self.transformation != transformation:
            self.transformation = transformation
            self.updateScaled()

    defupdateScaled(self):
        if self.pixmap:
            self.scaled = self.pixmap.scaled(self.size(), self.ratio, self.transformation)
        self.update()

    defsizeHint(self):
        return self._sizeHint

    defresizeEvent(self, event):
        self.updateScaled()

    defpaintEvent(self, event):
        ifnot self.pixmap:
            return
        qp = QPainter(self)
        r = self.scaled.rect()
        r.moveCenter(self.rect().center())
        qp.drawPixmap(r, self.scaled)


classWindow(QMainWindow):
    def__init__(self, parent=None):
        super().__init__(parent)
        self.imageLabel = ImageViewer(QPixmap.fromImage(image))
        self.setCentralWidget(self.imageLabel)

Solution 2:

Found a solution. Turns out putting the image inside a QScrollArea widget allows the window to be made smaller than the image it contains even if the scroll bars are disabled. This then allows the image to be rescaled to fit the window as the window size is reduced.

classWindow(QMainWindow):
    
    #scale image to change in window width (image is window width * window width square)defresizeEvent(self,event):
        self.image_scaled = image.scaled(self.scroll.width(),self.scroll.height()) 
        self.pixmap = QPixmap.fromImage(self.image_scaled)
        self.imageLabel.setPixmap(self.pixmap)  
        QMainWindow.resizeEvent(self, event)

    def__init__(self, parent=None):

        super().__init__(parent)
        self.setGeometry(100,100,200,200)   
        self.imageLabel = QLabel()
        self.scroll = QScrollArea()
        self.scroll.setWidget(self.imageLabel)
        self.setCentralWidget(self.scroll)

        self.scroll.setWidgetResizable(True)
        self.scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
      
        self.image_scaled = image.scaled(self.scroll.width(),self.scroll.width()) 
        self.pixmap = QPixmap.fromImage(self.image_scaled)
        self.imageLabel.setPixmap(self.pixmap)  

app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())

Post a Comment for "Resizing A Window With Pyqt5 - How Do I Reduce The Size Of A Widget To Allow The Window To Be Shrunk?"