【问题标题】:Scrollarea with fixed dimensions具有固定尺寸的滚动区域
【发布时间】:2021-08-02 22:27:49
【问题描述】:

我很抱歉标题,但我无法更好地解释这个主题。

我有一个带有网格布局的滚动区域,它具有可变数量的行和列。在网格的每个单元格中,我都有一个 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_()

【问题讨论】:

  • 我不确定我是否理解您想要的内容。这些“标签”是否总是具有相同的大小,可能基于缩放级别?您能否提供一些显示预期结果的图像?此外,请考虑设置将要添加到布局中的小部件的几何形状是完全没用的,因为无论如何布局都会覆盖该几何形状。
  • 谢谢!当我们必须指定它们的大小时,我只想了解不同小部件的交互。我可以在评论中发布图像吗?还是我必须修改主要信息?
  • 这是一个非常广泛的主题,在处理滚动区域时会变得非常复杂。基本概念是布局管理器完全按照他们的名字所说的那样做:他们管理项目的布局、它们的大小和它们的位置,考虑到可能的限制(最小/最大大小)、大小提示(首选大小)和policies(如何通过布局调整小部件的大小)。这就是为什么设置几何是没有意义的:布局负责。如果您想要固定大小,请使用setFixedSize()
  • 然后,您是说“如果设置为 True,我正在实施的缩放系统将不起作用”。什么“变焦系统”?我建议你澄清你在做什么以及你需要实现什么,如果“缩放系统”是强制性的,你应该向我们解释它的作用、方式和原因(可能通过扩展你的代码)。如果您想提供图片,请将其添加到帖子中;您当前的声誉不允许您嵌入它们,但其他用户将能够对其进行编辑以显示它。
  • 我只是在研究 GUI,所以现在对我来说更重要的是如何工作。如果我将此值设置为 true,我就有了我想要的布局(图像的左侧),但它的大小不可调整。所以我的第一个问题是:有没有办法通过使用内容小部件的某些属性而不是使用布局标志来获取左侧的布局?因为我不了解这种布局行为,如果我想了解这些库而不只是让应用程序工作,这对我来说很重要。

标签: python pyqt5 qlabel qscrollarea


【解决方案1】:

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

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

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

为了更好地理解 Qt 是如何处理所有这些(广泛而复杂的)方面的,我建议你阅读更多关于hints and policiesQSizePolicylayout management 的内容,并用更简单的方式做更多的实验 /em> 例,即使使用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)

我建议您对空格更加小心,在逗号后面(以及等号周围)应始终使用空格,以提高可读性。阅读更多官方Style Guide for Python Code

【讨论】:

  • 谢谢,我会研究你答案中的所有链接。也感谢您的风格建议:)
  • @Nunkij 不客气。请记住,如果一个答案解决了您的问题,您应该通过单击其左侧的灰色勾号将其标记为已接受(这是获得声誉的众多方法之一,这也将为您提供更多特权,例如发布的能力图片;见What is reputation)。
  • 如你所见,我是这个网站的新手,我不知道这个功能。我会尽快测试代码,以便我可以点击按钮 :) 再次感谢您!
猜你喜欢
  • 2021-11-04
  • 1970-01-01
  • 2019-12-11
  • 2013-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多