[Development] QWidget font settings propagation parent to child

Henry Skoglund henry at tungware.se
Wed Oct 23 16:28:22 CEST 2019


Hi,

I use Qt Creator's excellent Form Editor, however sometimes I've noticed 
an inconsistency in the font settings, because I'm lazy I usually only 
set the font property for the top MainWindow and relying on it to 
"trickle down" and affect the widgets as well. Except sometimes it 
doesn't trickle down :-( So I wrote a test app, just a main.cpp:

#include "QtWidgets"

int main(int argc, char** argv)
{
     QApplication a(argc,argv);
     QMainWindow w;

     auto listFonts = [&w]
     {
         for (auto pKid : 
w.findChildren<QWidget*>("",Qt::FindDirectChildrenOnly))
             qDebug() << pKid->metaObject()->className() << 
pKid->font().family();
     };

     w.setFont(QFont("Courier"));
     new QTextEdit(&w);
     new QLabel(&w);
     new QPushButton(&w);
     new QCalendarWidget(&w);
     new QListWidget(&w);
     new QTableWidget(&w);

     qDebug() << "Before w.show();"; listFonts();

     w.show();  // start the party

     qDebug() << "\nAfter w.show();"; listFonts();
}

The above app simulates what Qt Creator's Form Editor does (or, rather 
what the generated code in ui_mainwindow.h does), i.e. it sets the font 
prop for the MainWindow and then adds the children. If you run this 
program on Linux, the debug output is as expected:

Before w.show();
QTextEdit "Courier"
QLabel "Courier"
QPushButton "Courier"
QCalendarWidget "Courier"
QListWidget "Courier"
QTableWidget "Courier"

After w.show();
QTextEdit "Courier"
QLabel "Courier"
QPushButton "Courier"
QCalendarWidget "Courier"
QListWidget "Courier"
QTableWidget "Courier"

Everything is nice and dandy. However, running the same program on 
Windows gives this output (the Before part is the same)

...
After w.show();
QTextEdit "Courier"
QLabel "Courier"
QPushButton "Courier"
QCalendarWidget "Courier"
QListWidget "Tahoma"
QTableWidget "Tahoma"

Lost 2 font propagations there. And on the Mac it's even worse (the 
Before part is the same here, but):

...
After w.show();
QTextEdit "Courier"
QLabel ".AppleSystemUIFont"
QPushButton ".AppleSystemUIFont"
QCalendarWidget "Courier"
QListWidget ".AppleSystemUIFont"
QTableWidget ".AppleSystemUIFont"

Lost another 2, i.e. only 33% hit rate.

Now. the obvious solution is of course to always set the font properties 
explicitly for all widgets on my MainWindow. But it's so convenient to 
be able to change only the topmost font prop. Also the documentation for 
QWidget says "font propagation" should always occur. And sure, on Linux 
the docs are correct. But what about us running Windows or Macs?

Well, the first thing I tried was to reshuffle the lines in my test app:
...
     // w.setFont(QFont("Courier"));
     new QTextEdit(&w);
     new QLabel(&w);
     new QPushButton(&w);
     new QCalendarWidget(&w);
     new QListWidget(&w);
     new QTableWidget(&w);
     w.setFont(QFont("Courier"));
...

Setting the font *after* adding the children does the trick, the hit 
rate is now 100% also on Windows and Mac. But, the problem is that this 
isn't the way the Form Editor (ui_mainwindow.h) works, it is hardwired 
to always set the properties for the MainWindow before adding any children.


So as a workaround, I've resorted to adding one line of code in the 
MainWindow constructor in my Qt widget-flavored programs:
...
{
     ui->setupUi(this);

     auto f = font(); setFont(QFont("Grapefruit")); setFont(f);
...

Why the grapefruit? It's needed to "shake the tree", because when 
setting the same font as the code in ui_mainwindow.h does. it's ignored. 
You need to change to another font first, then the setFont(f) call will 
register properly (and propagate 100% to the kids). This can be 
illustrated if we change the test program to:
...
     w.setFont(QFont("Courier"));
     new QTextEdit(&w);
     new QLabel(&w);
     new QPushButton(&w);
     new QCalendarWidget(&w);
     new QListWidget(&w);
     new QTableWidget(&w);
     w.setFont(QFont("Courier"));
...

That version behaves exactly like the first version above (with the 
misses), i.e. like the 2nd setFont() call does not exist. But adding the 
dummy font call:
...
     w.setFont(QFont("Courier"));
     new QTextEdit(&w);
     new QLabel(&w);
     new QPushButton(&w);
     new QCalendarWidget(&w);
     new QListWidget(&w);
     new QTableWidget(&w);
     w.setFont(QFont("Grapefruit"));
     w.setFont(QFont("Courier"));
...

works, 100$ font prop propagation on all systems :-)


Question: is this hit or miss font propagation on Windows and Mac a bug 
or a feature? If it's a feature, could it be documented?

Rgrds Henry

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20191023/fb393097/attachment.html>


More information about the Development mailing list