在Qt中我有一个复合小部件,它由QBoxLayouts内部排列的几个QLabel组成。调整窗口小部件的大小时,我希望缩放标签文本以填充标签区域,并且我已在resizeEvent中实现了文本的大小调整。
这有效,但似乎有某种反馈循环发生。复合窗口小部件与其他一些窗口小部件一起放置在QBoxLayout内的主窗口中。当主窗口变小时,复合窗口小部件最初保持其大小,然后以几个步骤(大约10-15)调整到正确的大小。如果文本高度设置为标签高度的大约0.8倍,则在调整文本大小和包含小部件时,每个步骤都会变大,直到最终应用程序崩溃。
这是达到这种效果的正确方法吗?如果是这样,调整大小的问题可能是什么?
以下是resizeEvent代码。
def resizeEvent(self, evt):
print("resizeEvent", evt.size().width(), evt.size().height())
QFrame.resizeEvent(self, evt)
dataLabels = self.dataPanels.values()
for label in dataLabels:
font = label.font()
h = label.height()
h2 = h * 0.8
font.setPixelSize(h2)
label.setFont(font)
(使用PyQt4 4.8,Qt 4.7.4,Win 7& OSX 10.6)
答案 0 :(得分:8)
我认为SizePolicy
导致调整大小的问题。尝试将label
的尺寸政策设定为Ignored
它应该有所帮助。
label.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
这是达到这种效果的正确方法吗?
可能是的,快速搜索文档没有给出更好的解决方案。但我会创建QLabel
的子类,并在那里进行策略设置和调整大小。例如:
class StretchedLabel(QLabel):
def __init__(self, *args, **kwargs):
QLabel.__init__(self, *args, **kwargs)
self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
def resizeEvent(self, evt):
font = self.font()
font.setPixelSize(self.height() * 0.8)
self.setFont(font)
如果您不仅需要按高度调整文本,还需要按宽度调整文本,则需要一些附加代码。
答案 1 :(得分:0)
reclosedev's answer为我提供了使用Ignored
size policy的主要线索,但仍有一些细节需要解决。这是一个示例,该示例计算出适合标签当前大小的字体大小。
from PySide2.QtGui import QResizeEvent, QFontMetrics, Qt
from PySide2.QtWidgets import QLabel
class ScaledLabel(QLabel):
def resizeEvent(self, event: QResizeEvent):
# This flag is used for pixmaps, but I thought it might be useful to
# disable font scaling. Remove the check if you don't like it.
if not self.hasScaledContents():
return
target_rect = self.contentsRect()
text = self.text()
# Use binary search to efficiently find the biggest font that will fit.
max_size = self.height()
min_size = 1
font = self.font()
while 1 < max_size - min_size:
new_size = (min_size + max_size) // 2
font.setPointSize(new_size)
metrics = QFontMetrics(font)
# Be careful which overload of boundingRect() you call.
rect = metrics.boundingRect(target_rect, Qt.AlignLeft, text)
if (rect.width() > target_rect.width() or
rect.height() > target_rect.height()):
max_size = new_size
else:
min_size = new_size
font.setPointSize(min_size)
self.setFont(font)
不幸的是,当您使用缩放标签时,需要一些属性才能使此项工作。请确保始终设置它们,或覆盖__init__()
以使默认值有用。这是设置它们的工作示例:
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QApplication, QWidget, QVBoxLayout, QSizePolicy, QLabel
from scaled_label import ScaledLabel
def main():
app = QApplication()
widget = QWidget()
label1 = ScaledLabel('Lorem ipsum')
label2 = ScaledLabel('Lorem ipsum')
# Any policy other than Ignored will fight you when you resize.
size_policy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
label1.setSizePolicy(size_policy)
label2.setSizePolicy(size_policy)
# If you check this flag, don't forget to set it.
label1.setScaledContents(True)
label2.setScaledContents(True)
# "Ignored" policy means you have to define your own minimum size.
label1.setMinimumSize(200, 40)
label2.setMinimumSize(50, 10)
# Standard label attributes still work.
label1.setAlignment(Qt.AlignBottom)
label2.setAlignment(Qt.AlignTop)
# Tell the layout to scale the two fields at different sizes.
layout = QVBoxLayout(widget)
layout.addWidget(label1)
layout.addWidget(label2)
layout.setStretch(0, 4)
layout.setStretch(1, 1)
widget.show()
exit(app.exec_())
main()