Qt5 C++ resize font based on label width

I have written what I think is a pretty good font resize algorithm that I use on labels in a QGridLayout. The algorithm works rather well on its own. However, the first time I run the algorithm, the layout hasn't been painted yet, and as such, the grid widgets which own the labels haven't been sized to the layout, which means my width() call is wrong, though I have assigned the label text prior to the resize (which doesn't matter). My question is, what is the best way to know the bounding rectangles have been created to fit the layout so my calculation is on the actual label width?

Note, this is Qt5.7, so I know that fm.width() is obsolete, but that's what's available in Raspbian.

My app is reading Sonos metadata and showing it on a 7" RPi display. I'm resizing the metadata that is too long to fit in the layout grids. So, I have a QStackedLayout with a set of layouts to show (clock when Sonos isn't playing, metadata when it is), and I frequently poll the a local Sonos server to find out if there is metadata to show. This works well. What doesn't happen is that on the first time the Sonos metadata layout is shown, the QGridLayout hasn't actually been laid out yet (I believe), so the labels are too big. At some point after the first time I fill in the metadata, the grid layout gets "shown" and the labels are then the correct size. The problem is, by then, it's all done setting metadata and the labels look funny in some cases.

    int pointSize = FontSize::Default;

    for (auto label : m_labels) {
        QFont f = label->font();

        if (label->accessibleName() == "title")
            pointSize = FontSize::Title;

        QFontMetrics fm(f);
        if (fm.width(label->text()) > label->width()) {
            float factor = (float)label->width() / (float)fm.width(label->text());
            if (factor <= .6) {
                factor = .6;
            f.setPointSizeF((f.pointSize() * factor) * .9);
            qDebug() << __FUNCTION__ << ": label width:" << label->width();
            qDebug() << __FUNCTION__ << ": font width:" << fm.width(label->text());
            qDebug() << __FUNCTION__ << ": Calculated font scaling factor to be" << (float)(factor * .9);
            qDebug() << __FUNCTION__ << ": Reset font size for text\"" << label->text() << "\" to" << f.pointSize();


On an 800x480 display, this results in the first event label width being wrong

calculateLabelFontSize : label width: 640
calculateLabelFontSize : font width: 2051

The label width the next time it's called would end up being correct with a width of 584. However, because I don't always call it a second time, and because sometimes, the Sonos metadata hiccups and causes the display to revert, it may always be wrong, or it may just be right the first time no matter what.

I've considered trying to overload my gui app paintEvent(QPaintEvent *event), but the QPaintEvent class doesn't give me a way to determine which widget called for the event, so I can't just ignore the event until I want it. At least, not that I have determined, so if that's possible, please let me know.

I've tried overloading showEvent, but that doesn't run except when the frame is first shown, so no help there.

I've considered subclassing QGridLayout to simply overload the paintEvent() and use that, but I do have an issue with that solution. There is a progress bar in this layout, which means that the paintEvent is going to fire every half second as I get metadata from the Sonos server. Since I don't know if the paintEvent is firing for the time update, or for the text being set, I get a lot of resize attempts.

I've also simply run the algorithm a second time on the next event, but it's a really weird looking graphical hiccup when the fonts realign, and I don't like it.

Last up, I may just subclass QLabel, simply to overload paintEvent, and use that custom label just for the labels that would be resizable. However, is the label in the layout painted before or after the container it lives in inside the layout? I'll be testing this today I think, but I'm not convinced it would work.

I figure this has a much easier solution though. I just can't figure it out.