首页 > 解决方案 > 具有固定尺寸的滚动区域

问题描述

我很抱歉标题,但我不能以更好的方式解释这个话题。

我有一个带有 gridlayout 的滚动区域,它具有可变数量的行和列。在网格的每个单元格中,我都有一个 QLabel。我希望滚动区域的视口具有固定大小,因此我可以在不使用滚动条的情况下仅查看一定数量的标签。相反,在这段代码中,我查看了所有标签,如果它们的数量变化,它们总是插入到视口空间中,并且它们的尺寸发生了变化。

我应该在不更改 self.scrollArea.setWidgetResizable(False) 行的情况下执行此操作,因为如果设置为 True,我正在实施的缩放系统将不起作用。

可能吗?

import sys


from PyQt5.QtCore import Qt, QRect
from PyQt5.QtWidgets import ( QVBoxLayout, QHBoxLayout, QGridLayout, QApplication, QMainWindow,
                             QLabel, QWidget, QPushButton, QScrollArea
                             )



class MyScrollingArea(QWidget):

    def __init__(self, parent=None):
        super(MyScrollingArea).__init__()
        self.vertLayout = QVBoxLayout()
        self.vertLayout.setContentsMargins(0, 0, 0, 0)
        self.vertLayout.setSpacing(0)
        self.gridLayout = QGridLayout()
        self.gridContainer = QWidget()
        self.scrollArea = QScrollArea()
        self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setWidget(self.gridContainer)
        self.populate( )
        buttonsArea=self.zoomMenu()
        self.gridContainer.setLayout(self.gridLayout )
        self.vertLayout.addWidget(self.scrollArea)
        self.vertLayout.addWidget(buttonsArea)
        self.setLayout(self.vertLayout )

    def zoomMenu(self):
           widButtonFooter = QWidget()
           layButtonFooter = QHBoxLayout()
           widButtonFooter.setLayout(layButtonFooter)
           butZommMinus = QPushButton("-")
           butZommPlus = QPushButton("+")
           layButtonFooter.addWidget(butZommMinus)
           layButtonFooter.addWidget(butZommPlus) 
           return widButtonFooter

    def populate(self):
        colors = (  "navy","green", "magenta","cyan", "yellow","red", "orange", "blue","purple", "gold","silver", "lightblue", "lime" )
        for row in range(0,10):
            for col in range (0,20):
                self.addLabel(row,col,colors[row])

    def addLabel(self,row,col,color):
        label = MyLabel(row,col,80,100,color,str(row) + "." + str(col))
        self.gridLayout.addWidget(label,row,col) 

    def resizeEvent(self, event):
        self.gridContainer.resize(self.width(), self.height())
        super(MyScrollingArea, self).resizeEvent(event)



class MyLabel(QLabel):
    def __init__(self,row,col, w, h, color, text):
        super().__init__()
        self.color=color
        self.setStyleSheet("border:10px solid " + self.color + ";")
        self.setText(text)
        self.setAlignment(Qt.AlignCenter)
        self.setGeometry(QRect(0, 0, w, h))

    def mousePressEvent(self,QMouseEvent):
        if QMouseEvent.button() == Qt.LeftButton:
            self.setStyleSheet("background-color:" + self.color + ";")
        elif QMouseEvent.button() == Qt.RightButton:
            self.setStyleSheet("border:10px solid " + self.color + ";")

class MyGrid(QMainWindow):

    def __init__(self):
        super().__init__()
        self.resize(1000, 800)
        self.saScrollMeasureBox = MyScrollingArea()
        widPanelMeasure = QWidget()
        layvPanelMeasure = QVBoxLayout()
        widPanelMeasure.setLayout(layvPanelMeasure)
        layvPanelMeasure.addWidget(self.saScrollMeasureBox)
        self.setCentralWidget(widPanelMeasure)
        
        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MyGrid()

    window.show()
    app.exec_()

截图应用

标签: pythonpyqt5qlabelqscrollarea

解决方案


布局管理器没有特定的尺寸,只有尺寸提示,可能还有最小和/或最大尺寸,所有这些都基于它包含的项目,使用它们的尺寸提示、约束和策略。

在要添加到布局的小部件上设置几何图形是没有意义的,因为布局管理它们的大小和位置。解决方案是setFixedSize改用。

由于如果有剩余空间,布局也会自动调整小部件的位置(并且它们都无法扩展其大小),因此您可以在布局的末尾添加一个拉伸以确保它们始终保持相同的间距即使边缘有更多可用空间。对于盒装布局,使用 就足够了addStretch(),但对于网格布局,您必须指定特定行和列的拉伸。

为了更好地理解 Qt 是如何处理所有这些(广泛而复杂的)方面的,我建议您阅读更多关于提示和策略QSizePolicy布局管理的内容,并使用更简单的案例进行更多实验,甚至使用Designer

以下修改要求将该widgetResizable属性设置为True

class MyScrollingArea(QWidget):
    # ...
    def populate(self):
        colors = (
            "navy", "green", "magenta", "cyan", "yellow", "red", "orange", 
            "blue", "purple", "gold", "silver", "lightblue", "lime"
        )
        rows = 10
        columns = 20
        for row in range(rows):
            for col in range (columns):
                self.addLabel(row, col, colors[row])
        self.gridLayout.setColumnStretch(columns, 1)
        self.gridLayout.setRowStretch(rows, 1)


class MyLabel(QLabel):
    def __init__(self, row, col, w, h, color, text):
        super().__init__()
        self.color = color
        self.setStyleSheet("border:10px solid " + self.color + ";")
        self.setText(text)
        self.setAlignment(Qt.AlignCenter)
        self.setFixedSize(w, h)

我建议您对空格更加小心,在逗号后面(以及等号周围)应始终使用空格,以提高可读性。阅读更多关于 Python 代码的官方样式指南


推荐阅读