Python 自定义布局管理器中缺少子窗口小部件的调整大小事件
在PyQt5中,我尝试使用一个()来缩放标签图像。当使用普通的BoxLayout进行测试时,缩放图像本身的工作方式与预期的一样,并在执行缩放时实现方法Python 自定义布局管理器中缺少子窗口小部件的调整大小事件,python,qt,pyqt,pyqt5,qt5,Python,Qt,Pyqt,Pyqt5,Qt5,在PyQt5中,我尝试使用一个()来缩放标签图像。当使用普通的BoxLayout进行测试时,缩放图像本身的工作方式与预期的一样,并在执行缩放时实现方法resizeEvent(self,evt) 但是,当我尝试将其用于自定义FlowLayout时,标签图像在调整外部容器大小时不再接收调整大小事件(侦听器在小部件创建时仅执行一次),因此图像不会缩放。这里可以看到问题: 收缩后,将剪切图像: 为什么图像不再接收resizeEvent 布局管理器的代码来自: #来自Qt文档并由jonB修改/改编的代
resizeEvent(self,evt)
但是,当我尝试将其用于自定义FlowLayout时,标签图像在调整外部容器大小时不再接收调整大小事件(侦听器在小部件创建时仅执行一次),因此图像不会缩放。这里可以看到问题:
收缩后,将剪切图像:
为什么图像不再接收resizeEvent
布局管理器的代码来自:
#来自Qt文档并由jonB修改/改编的代码
类流布局(QLayout):
def uu init uuu(self,parent:QWidget=None,margin:int=-1,hSpacing:int=-1,vSpacing:int=-1):
super()。\uuuu init\uuuu(父级)
self.itemList=list()
self.m_hSpace=hSpacing
self.m_vSpace=vSpacing
self.setContentsMargins(边距、边距、边距、边距)
定义(自我):
#为保持一致性而复制,不确定是否需要或是否调用过
item=self.takeAt(0)
而项目:
item=self.takeAt(0)
def附加项(自身,项目:QLayoutItem):
self.itemList.append(项)
def水平间距(自)->int:
如果self.m_hSpace>=0:
返回self.m_hSpace
其他:
返回self.smartSpacing(QStyle.PM_layouuthorizontalspacking)
def垂直间距(自)->int:
如果self.m_vSpace>=0:
返回self.m_vSpace
其他:
返回self.smartSpacing(QStyle.PM\U布局垂直间距)
def计数(自身)->int:
返回len(self.itemList)
def itemAt(self,index:int)->typing.Union[QLayoutItem,None]:
如果0正在键入.Union[QLayoutItem,无]:
如果0 Qt.方向:
返回Qt.方向(Qt.方向(0))
def hasHeightForWidth(自)->bool:
返回真值
def heightForWidth(self,width:int)->int:
高度=self.doLayout(QRect(0,0,宽度,0),真)
返回高度
def setGeometry(自身、直肠:QRect)->无:
super().setGeometry(rect)
自我分配(正确,错误)
def sizeHint(自身)->QSize:
返回self.minimumSize()
def最小尺寸(自身)->QSize:
size=QSize()
对于self.itemList中的项目:
size=size.expandedTo(item.minimumSize())
页边距=self.contentsMargins()
size+=QSize(margins.left()+margins.right()、margins.top()+margins.bottom())
返回大小
def smartSpacing(self,pm:QStyle.PixelMetric)->int:
parent=self.parent()
如果不是家长:
返回-1
elif parent.isWidgetType():
返回parent.style().pixelMetric(pm,None,parent)
其他:
返回parent.spating()
def-doLayout(self、rect:QRect、testOnly:bool)->int:
左、上、右、下=self.getContentsMargins()
effectiveRect=调整后的直线(+左、+上、-右、-下)
x=effectivelect.x()
y=有效的影响因素。y()
线宽=0
对于self.itemList中的项目:
wid=item.widget()
spaceX=self.horizontalSpacing()
如果spaceX==-1:
spaceX=wid.style().layoutSpacing(QSizePolicy.butdown、QSizePolicy.butdown、Qt.Horizontal)
spaceY=self.verticalSpacing()
如果spaceY==-1:
spaceY=wid.style().layoutSpacing(QSizePolicy.butdown、QSizePolicy.butdown、Qt.Vertical)
nextX=x+item.sizeHint().width()+spaceX
如果nextX-spaceX>effectiveRect.right()且线宽>0:
x=effectivelect.x()
y=y+线宽+空格y
nextX=x+item.sizeHint().width()+spaceX
线宽=0
如果不只是测试:
item.setGeometry(QRect(QPoint(x,y),item.sizeHint())
x=nextX
lineHeight=max(lineHeight,item.sizeHint().height())
返回y+线宽-矩形y()+底部
resizeEvent
仅在调整标签大小时才会在标签上调用。布局管理器FlowLayout
从未调整其子项的大小。请参见doLayout
item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
在这里,子项的新大小被设置为item.sizeHint()
,默认情况下,它是item
的当前大小(可以通过覆盖小部件类中标签的sizeHint
来更改)
以下更新的doLayout
使用sizeHint()
,前提是容器宽度足以显示至少一个项目。否则,将调整项目的大小(保持纵横比),以便在一列中完全显示其宽度。此代码仅用于说明。您仍然需要进行更精细的调整,以将间距和边框合并到调整大小计算中。更改用标记。
def doLayout(self, rect: QRect, testOnly: bool) -> int:
left, top, right, bottom = self.getContentsMargins()
effectiveRect = rect.adjusted(+left, +top, -right, -bottom)
x = effectiveRect.x()
y = effectiveRect.y()
lineHeight = 0
for item in self.itemList:
###########################
itemSize = item.sizeHint()
itemNewWidth = min(rect.width(), itemSize.width())
itemSize = QtCore.QSize(itemNewWidth, itemSize.height() * itemNewWidth / itemSize.width())
wid = item.widget()
spaceX = self.horizontalSpacing()
if spaceX == -1:
spaceX = wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal)
spaceY = self.verticalSpacing()
if spaceY == -1:
spaceY = wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical)
nextX = x + item.sizeHint().width() + spaceX
if nextX - spaceX > effectiveRect.right() and lineHeight > 0:
x = effectiveRect.x()
y = y + lineHeight + spaceY
nextX = x + item.sizeHint().width() + spaceX
lineHeight = 0
if not testOnly:
###########################
item.setGeometry(QRect(QPoint(x, y), itemSize))
x = nextX
###########################
lineHeight = max(lineHeight, itemSize.height())
return y + lineHeight - rect.y() + bottom
要使此项工作正常,您可能必须重新定义标签的sizeHint()
,以返回固定大小(而不是当前大小)
def doLayout(self, rect: QRect, testOnly: bool) -> int:
left, top, right, bottom = self.getContentsMargins()
effectiveRect = rect.adjusted(+left, +top, -right, -bottom)
x = effectiveRect.x()
y = effectiveRect.y()
lineHeight = 0
for item in self.itemList:
###########################
itemSize = item.sizeHint()
itemNewWidth = min(rect.width(), itemSize.width())
itemSize = QtCore.QSize(itemNewWidth, itemSize.height() * itemNewWidth / itemSize.width())
wid = item.widget()
spaceX = self.horizontalSpacing()
if spaceX == -1:
spaceX = wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal)
spaceY = self.verticalSpacing()
if spaceY == -1:
spaceY = wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical)
nextX = x + item.sizeHint().width() + spaceX
if nextX - spaceX > effectiveRect.right() and lineHeight > 0:
x = effectiveRect.x()
y = y + lineHeight + spaceY
nextX = x + item.sizeHint().width() + spaceX
lineHeight = 0
if not testOnly:
###########################
item.setGeometry(QRect(QPoint(x, y), itemSize))
x = nextX
###########################
lineHeight = max(lineHeight, itemSize.height())
return y + lineHeight - rect.y() + bottom
def sizeHint(self):
return QtCore.QSize(preferredWidth, preferredHeight)