Measure a wrapped label against a width it actually has

The publisher note is written while the settings window is still being
built, when its label is eight pixels wide. Wrapped against that width the
sentence came out a hundred and twenty lines tall, and the minimum taken
from it did not stay a minimum: QLabel folds the widget's minimum size into
its own cached size hints and clears that cache only when the text changes.
So the row stood two thousand pixels tall, carrying the model box, the
status line and the options under it off the bottom of the window, and
picking another publisher was what brought them back.

Nothing to measure against yet means nothing to claim yet. The show and the
resize come back for it once there is a real width.
This commit is contained in:
2026-09-05 12:07:13 +03:00
parent 06e578d901
commit 44db26c459
2 changed files with 47 additions and 5 deletions
+21 -5
View File
@@ -181,18 +181,34 @@ class WrappedLabel(QLabel):
super().setText(text)
self._fit()
def showEvent(self, event):
# Text set while the window was still being built was measured against
# nothing; this is the first moment the width means anything.
super().showEvent(event)
self._fit()
def resizeEvent(self, event):
super().resizeEvent(event)
self._fit()
def _fit(self):
# A label the layout has not placed yet is a handful of pixels wide,
# and wrapping a sentence against that width invents a hundred lines.
# The minimum set from it does not stay a minimum either: QLabel folds
# it into its own cached size hints and clears that cache only when the
# text changes, so the row stands thousands of pixels tall and carries
# the model box and everything under it off the bottom of the window
# until another publisher is picked. Nothing to measure against yet
# means nothing to claim yet, and the show and resize above come back
# for it.
if not self.isVisible() or self.width() <= 0:
return
# Measured off the font rather than asked of the label, whose own answer
# is floored by the minimum set here a moment ago and so only ever grows.
if self.width() > 0:
wrap = Qt.TextFlag.TextWordWrap | Qt.TextFlag.TextWrapAnywhere
box = QRect(0, 0, self.width(), 0)
self.setMinimumHeight(
self.fontMetrics().boundingRect(box, wrap, self.text()).height())
wrap = Qt.TextFlag.TextWordWrap | Qt.TextFlag.TextWrapAnywhere
box = QRect(0, 0, self.width(), 0)
self.setMinimumHeight(
self.fontMetrics().boundingRect(box, wrap, self.text()).height())
class WheelGuard(QObject):