measure the card against every one of its layouts
Changing a label's text posts a LayoutRequest to the widget holding it, and that event is only delivered when the event loop next runs. The panel measured its card by invalidating the body's own layout alone, so any layout nested inside the card -- which is all of them -- still answered with the width of the text before the change. The panel therefore placed itself against the previous values and corrected itself on the following refresh, a frame late. Measured on a BarRow: with the value going idle, 0%, 42%, 100% the panel's measurement reported 16, 16, 17, 23 where the settled widths were 16, 17, 23, 29 -- one change behind throughout. Re-activating every layout in the card gives the settled answer without waiting for the event loop. This is not the size change the player reported, which I could not reproduce here; it is a second, quieter one found while looking for it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcReq7hVk4KUPhTDKWAG7K
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
#include "SelectionPanel.h"
|
#include "SelectionPanel.h"
|
||||||
|
|
||||||
|
#include <QLayout>
|
||||||
|
#include <QList>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
@@ -263,9 +265,16 @@ void SelectionPanel::placeIn(const QRect& viewRect, const std::vector<QRect>& oc
|
|||||||
// laid out, does the width it reports. Measuring at whatever width the panel
|
// laid out, does the width it reports. Measuring at whatever width the panel
|
||||||
// happens to have carries the previous card's shape into this one.
|
// happens to have carries the previous card's shape into this one.
|
||||||
//
|
//
|
||||||
// Each measurement re-runs the body layout. Cards are built and discarded whole, so
|
// Each measurement re-runs the card's layouts -- every one of them, not just the
|
||||||
// its cached hint describes the card before this one until it is invalidated, and
|
// body's own. Changing a label's text posts a LayoutRequest to the widget holding it
|
||||||
// re-running it is also what accounts for the parts a card hides and shows as it
|
// and that event is only delivered when the event loop next runs, so a layout nested
|
||||||
|
// inside the card still reports the width of the text before the change: measuring
|
||||||
|
// here and re-measuring on the following refresh then gives two different answers,
|
||||||
|
// and the panel visibly resizes a frame after its content changed. Re-activating
|
||||||
|
// them all is what a delivered LayoutRequest would have done.
|
||||||
|
//
|
||||||
|
// Cards are built and discarded whole, so this is also what discards the previous
|
||||||
|
// card's cached hints, and what accounts for the parts a card hides and shows as it
|
||||||
// refreshes. The polish belongs to the same step: a freshly created chip reports an
|
// refreshes. The polish belongs to the same step: a freshly created chip reports an
|
||||||
// unstyled hint until the stylesheet has reached it, and the chips carry border and
|
// unstyled hint until the stylesheet has reached it, and the chips carry border and
|
||||||
// padding that change their size.
|
// padding that change their size.
|
||||||
@@ -273,6 +282,16 @@ void SelectionPanel::placeIn(const QRect& viewRect, const std::vector<QRect>& oc
|
|||||||
{
|
{
|
||||||
m_body->resize(widthPx, m_body->height());
|
m_body->resize(widthPx, m_body->height());
|
||||||
m_body->ensurePolished();
|
m_body->ensurePolished();
|
||||||
|
|
||||||
|
// Deepest first, so no layout is re-activated from children that are themselves
|
||||||
|
// still stale. findChildren walks parents before children, hence the reverse.
|
||||||
|
const QList<QLayout*> nested = m_body->findChildren<QLayout*>();
|
||||||
|
for (QList<QLayout*>::const_reverse_iterator it = nested.rbegin();
|
||||||
|
it != nested.rend(); ++it)
|
||||||
|
{
|
||||||
|
(*it)->invalidate();
|
||||||
|
(*it)->activate();
|
||||||
|
}
|
||||||
m_body->layout()->invalidate();
|
m_body->layout()->invalidate();
|
||||||
m_body->layout()->activate();
|
m_body->layout()->activate();
|
||||||
return m_body->sizeHint();
|
return m_body->sizeHint();
|
||||||
|
|||||||
Reference in New Issue
Block a user