我有 PyQt5 QLabels,可以随着 QMainWindow 大小的变化而扩展/收缩。当 QMainWindow 的大小调整为其初始尺寸以外的任何值时,我想获取 QLabels 的尺寸。
下面的脚本在 QMainWindow 中创建两个 QLabel。 QLabel 展开,但顶部 QLabel 具有固定高度。 QMainWindow 的创建尺寸为 400x300,并使用
showMaximized()
显示为最大化的屏幕(在我的例子中,为 1920 x 1080)。该脚本在 QMainWindow 显示之前和之后打印 QLabels 的尺寸。在显示之前, width()
和 height()
返回默认的 QLabel 值,在显示之后(屏幕最大化) width()
和 height()
返回值,就好像 QMainWindow 的物理尺寸为 400x300 一样。这是打印的:
label_1 Size Before Expanding: 100 100
label_2 Size Before Expanding: 100 30
label_1 Size After Expanding: 378 100
label_2 Size After Expanding: 378 171
当 QMainWindow 最大化时,如何获得 QLabels 的真实尺寸?我在Windows环境下运行。
from PyQt5.QtWidgets import QApplication, QMainWindow, QSizePolicy, QLabel, QVBoxLayout, QWidget
import sys
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
central_widget = QWidget()
self.setCentralWidget(central_widget)
self.setGeometry(100, 100, 400, 300)
self.layout = QVBoxLayout(central_widget)
self.label_1 = QLabel(self)
self.label_1.setStyleSheet('background-color: green')
self.label_1.setFixedHeight(100)
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.label_1.setSizePolicy(sizePolicy)
self.layout.addWidget(self.label_1)
self.label_2 = QLabel(self)
self.label_2.setStyleSheet('background-color: red')
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.label_2.setSizePolicy(sizePolicy)
self.layout.addWidget(self.label_2)
print('label_1 Size Before Expanding: ', self.label_1.width(), self.label_1.height())
print('label_2 Size Before Expanding: ', self.label_2.width(), self.label_2.height())
self.showMaximized()
print('label_1 Size After Expanding: ', self.label_1.width(), self.label_1.height())
print('label_2 Size After Expanding: ', self.label_2.width(), self.label_2.height())
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
app.exec()
当小部件已创建但尚未在屏幕上映射(“显示”)时,它们始终具有默认大小:
setParent()
);唯一的例外是存在尺寸限制时,就像您的情况一样:第一个标签具有固定高度,这就是输出中显示的内容(请记住,“固定尺寸”意味着最小和最大尺寸相同).
第一次调用show()
或
setVisible(True)
时,会在顶层或父窗口小部件上自动创建(除其他外)一个
Resize
事件,该事件会自动激活该窗口小部件的布局,并最终递归地为所有窗口创建
Resize
事件基于布局计算,由其布局管理的小部件。在第一次显示小部件之前,这不会发生。这样做是出于优化原因:更新布局可能非常困难,特别是对于具有多个嵌套布局的复杂 UI,其中包含具有不同大小提示、策略、拉伸等的小部件。 由于一旦显示窗口,几何图形就会更新,因此在完整布局完成之前设置尺寸是没有意义的。另请注意,第一次使用
setGeometry()
resize()
prior
显示小部件将不会 激活布局,如上所述。 也就是说,即使尚未显示小部件,也可以根据当前布局更新尺寸:您必须显式地
activate()
布局管理器。这通常也可以通过调用布局的 sizeHint()
、
after在其小部件上设置来实现。
但是,请注意:为了根据布局获得正确的尺寸,您需要激活所有布局,直到顶级小部件。 QMainWindow 有自己的私有布局,因此您也需要激活它。 由于您已使用
layout()
覆盖了默认的 self.layout
函数,因此访问它的唯一方法是通过
super()
调用。
然后,还有另一个问题:更改窗口状态(最大化、最小化、全屏和正常)的函数不会直接调整窗口大小。这些函数(包括
setWindowState()
)实际上“请求”操作系统更改窗口状态,然后操作系统将自行决定请求是否可接受,并最终根据请求状态根据其行为调整窗口大小。调整大小将在调用后的“未定义”点发生,并且没有直接的方法知道何时:操作系统可能有一些奇特的动画来显示状态更改,这可能会导致大小连续变化,甚至突然变化“过程”完成后调整为新尺寸。即使使用
processEvents()
也是不够的,因为该函数仅处理由 Qt 直接处理的事件,而 Qt 无法了解有关外部操作系统事件的任何信息。 在调整大小后
确定小部件尺寸的唯一方法是覆盖
resizeEvent()
class MainWindow(QMainWindow):
def __init__(self, parent=None):
# ...
super().layout().activate()
self.layout.activate()
print('label_1 Size Before Showing: ', self.label_1.size())
print('label_2 Size Before Showing: ', self.label_2.size())
self.showMaximized()
def resizeEvent(self, event):
super().resizeEvent(event)
print('label_1 Size After Showing/Resizing: ', self.label_1.size())
print('label_2 Size After Showing/Resizing: ', self.label_2.size())
这将在showMaximized()
之前正确打印:
label_1 Size Before Expanding: PyQt5.QtCore.QSize(388, 100)
label_2 Size Before Expanding: PyQt5.QtCore.QSize(388, 182)
label_1 Size After Resizing: PyQt5.QtCore.QSize(388, 100)
label_2 Size After Resizing: PyQt5.QtCore.QSize(388, 182)
label_1 Size After Resizing: PyQt5.QtCore.QSize(1428, 100)
label_2 Size After Resizing: PyQt5.QtCore.QSize(1428, 757)
resizeEvent
被调用两次:第一次是在任何
show*()
调用之后,第二次是在窗口实际最大化时。如果删除上面的
activate
调用,第一个输出将与开头解释的默认值相同。
要获得真实大小,我认为您需要触发 resizeEvent。我不知道在查询大小之前强制事件循环完成最大化的方法。当你在 __init__ 中运行它时,甚至
app.processEvents()
似乎对此没有影响:from PyQt5.QtWidgets import QApplication, QMainWindow, QSizePolicy, QLabel, QVBoxLayout, QWidget
import sys
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
central_widget = QWidget()
self.setCentralWidget(central_widget)
self.setGeometry(100, 100, 400, 300)
self.layout = QVBoxLayout(central_widget)
self.label_1 = QLabel(self)
self.label_1.setStyleSheet('background-color: green')
self.label_1.setFixedHeight(100)
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.label_1.setSizePolicy(sizePolicy)
self.layout.addWidget(self.label_1)
self.label_2 = QLabel(self)
self.label_2.setStyleSheet('background-color: red')
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.label_2.setSizePolicy(sizePolicy)
self.layout.addWidget(self.label_2)
self.show()
# ~ print('label_1 Size Before Expanding: ', self.label_1.width(), self.label_1.height())
# ~ print('label_2 Size Before Expanding: ', self.label_2.width(), self.label_2.height())
self.showMaximized()
# ~ print('label_1 Size After Expanding: ', self.label_1.width(), self.label_1.height())
# ~ print('label_2 Size After Expanding: ', self.label_2.width(), self.label_2.height())
def resizeEvent(self, event):
print('label_1 Size : ', self.label_1.width(), self.label_1.height())
print('label_2 Size : ', self.label_2.width(), self.label_2.height())
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
app.exec()
这给出了