【问题标题】:Resizing a window with PyQT5 - how do I reduce the size of a widget to allow the window to be shrunk?使用 PyQT5 调整窗口大小 - 如何减小小部件的大小以缩小窗口?
【发布时间】:2021-08-29 02:30:21
【问题描述】:

我正在尝试通过重新制作用于处理像素艺术的旧命令行 C 程序来学习它。

目前,主窗口以单个 QLabel 设置开始,以显示 10 x 10 白色图像的 300 x 300 放大版本。

我正在使用 resizeEvent(我也尝试过使用 paintEvent 来解决同样的问题)在窗口大小增加时重新缩放图像以填充窗口。

我的问题是,当窗口大小减小时,如何重新缩放图像以适应窗口?就目前而言,窗口的大小不能调整为小于显示图像的小部件。本质上,我可以让窗口(和图像)更大,但永远不会变小。

到目前为止,我的代码如下。就目前而言,它仅根据窗口宽度的变化工作,只是为了在我解决这个问题时保持简单。有没有办法让窗口调整为小于最大的小部件?或者有没有更好的方法来解决这个问题?

#Create white 10*10 image
image = QImage(10,10,QImage.Format.Format_ARGB32)
image_scaled = QImage()
image.fill(QColor(255,255,255)) 

class Window(QMainWindow):
    
    #scale image to change in window width (image is window width * window width square)
    def resizeEvent(self,event):
        if self.imageLabel.width()>self.imageLabel.height(): 
            self.image_scaled = image.scaled(self.imageLabel.width(),self.imageLabel.width()) 
            self.pixmap = QPixmap.fromImage(self.image_scaled)
            self.imageLabel.setPixmap(self.pixmap)  
        QWidget.resizeEvent(self, event)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setGeometry(100,100,300,300)   
        self.imageLabel = QLabel()
        self.setCentralWidget(self.imageLabel)
        
        self.image_scaled = image.scaled(self.imageLabel.width(),self.imageLabel.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_())

【问题讨论】:

    标签: python user-interface pyqt pyqt5


    【解决方案1】:

    虽然 OP 提出的解决方案可能有效,但它有一个重要的缺点:它将 QScrollArea 用于错误的目的(因为它从未用于滚动)。这种方法在调整大小时会产生不必要的开销,因为视图需要在“完成”调整大小事件(包括滚动条范围和几何图形)之前计算很多关于其内容的事情,这些事情最终将永远不会被实际使用。

    主要问题在于 QLabel 不允许将大小调整为小于原始像素图集的大小。要解决这个问题,最简单的解决方案是创建一个自定义 QWidget 子类,它自己绘制像素图。

    class ImageViewer(QWidget):
        pixmap = None
        _sizeHint = QSize()
        ratio = Qt.KeepAspectRatio
        transformation = Qt.SmoothTransformation
    
        def __init__(self, pixmap=None):
            super().__init__()
            self.setPixmap(pixmap)
    
        def setPixmap(self, pixmap):
            if self.pixmap != pixmap:
                self.pixmap = pixmap
                if isinstance(pixmap, QPixmap):
                    self._sizeHint = pixmap.size()
                else:
                    self._sizeHint = QSize()
                self.updateGeometry()
                self.updateScaled()
    
        def setAspectRatio(self, ratio):
            if self.ratio != ratio:
                self.ratio = ratio
                self.updateScaled()
    
        def setTransformation(self, transformation):
            if self.transformation != transformation:
                self.transformation = transformation
                self.updateScaled()
    
        def updateScaled(self):
            if self.pixmap:
                self.scaled = self.pixmap.scaled(self.size(), self.ratio, self.transformation)
            self.update()
    
        def sizeHint(self):
            return self._sizeHint
    
        def resizeEvent(self, event):
            self.updateScaled()
    
        def paintEvent(self, event):
            if not self.pixmap:
                return
            qp = QPainter(self)
            r = self.scaled.rect()
            r.moveCenter(self.rect().center())
            qp.drawPixmap(r, self.scaled)
    
    
    class Window(QMainWindow):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.imageLabel = ImageViewer(QPixmap.fromImage(image))
            self.setCentralWidget(self.imageLabel)
    

    【讨论】:

    • 太好了,谢谢。不仅是我不知道你可以做的事情,还有我不知道我应该做的事情。
    【解决方案2】:

    找到了解决办法。事实证明,即使滚动条被禁用,将图像放在 QScrollArea 小部件中也可以使窗口小于它包含的图像。然后,当窗口大小减小时,这允许重新缩放图像以适应窗口。

    class Window(QMainWindow):
        
        #scale image to change in window width (image is window width * window width square)
        def resizeEvent(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_())
    

    【讨论】:

      猜你喜欢
      • 2015-05-08
      • 2011-05-18
      • 1970-01-01
      • 1970-01-01
      • 2013-03-27
      • 2016-06-01
      • 1970-01-01
      • 2018-03-01
      • 1970-01-01
      相关资源
      最近更新 更多