问题描述
我有一个带有 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)
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,color):
label = MyLabel(row,80,100,color,str(row) + "." + str(col))
self.gridLayout.addWidget(label,col)
def resizeEvent(self,event):
self.gridContainer.resize(self.width(),self.height())
super(MyScrollingArea,self).resizeEvent(event)
class MyLabel(QLabel):
def __init__(self,w,h,text):
super().__init__()
self.color=color
self.setStyleSheet("border:10px solid " + self.color + ";")
self.setText(text)
self.setAlignment(Qt.AlignCenter)
self.setGeometry(QRect(0,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_()
解决方法
布局管理器没有特定的大小,只有一个大小提示,可能还有一个最小和/或最大大小,所有这些都基于它包含的项目,使用它们的大小提示、约束和策略。
在要添加到布局中的小部件上设置几何图形毫无意义,因为布局管理它们的大小和位置。解决方案是改用 setFixedSize
。
由于布局还会在有剩余空间时自动调整小部件的位置(并且它们都无法扩展其大小),因此您可以在布局末尾添加拉伸以确保它们始终保持间隔即使边缘有更多可用空间,也是如此。对于盒装布局,使用 addStretch()
就足够了,但对于网格布局,您必须改为指定特定行和列的拉伸。
为了更好地理解 Qt 如何处理所有这些(广泛而复杂的)方面,我建议您阅读更多关于 hints and policies、QSizePolicy 和 layout management 的内容,并使用更简单的情况,甚至使用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,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 的更多信息。