Changing font size of all QLabel objects PyQt5
Asked Answered
E

4

7

I had written a gui using PyQt5 and recently I wanted to increase the font size of all my QLabels to a particular size. I could go through the entire code and individually and change the qfont. But that is not efficient and I thought I could just override the class and set all QLabel font sizes to the desired size.

However, I need to understand the class written in python so I can figure out how to override it. But I did not find any python documentation that shows what the code looks like for QLabel. There is just documentation for c++. Hence, I wanted to know where I can get the python code for all of PyQt5 if that exists? If not, how can I change the font size of all QLabels used in my code?

Eructate answered 16/8, 2020 at 22:15 Comment(0)
R
14

While the provided answers should have already given you enough suggestions, I'd like to add some insight.

Are there python sources for Qt?

First of all, you cannot find "the class written in python", because (luckily) there's none. PyQt is a binding: it is an interface to the actual Qt library, which is written in C++.

As you might already know, while Python is pretty fast on nowadays computers, it's not that fast, so using a binding is a very good compromise: it allows the simple syntax Python provides, and gives all speed provided by C++ compiled libraries under the hood.

You can find the source code for Qt widgets here (official mirror), or here.

How to override the default font?

Well, this depends on how you're going to manage your project.

Generally speaking, you can set the default font [size] for a specific widget, for its child widgets, for the top level window or even for the whole application. And there are at least two ways to do it.

  1. use setFont(): it sets the default font for the target; you can get the current default font using something.font(), then use font.setPointSize() (or setPointSizeF() for float values, if the font allows it) and then call setFont(font) on the target.
  2. use font[-*] in the target setStyleSheet();

Target?

The target might be the widget itself, one of its parents or even the QApplication.instance(). You can use both setFont() or setStyleSheet() on any of them:

    font = self.font()
    font.setPointSize(24)
    # set the font for the widget:
    self.pushButton.setFont(someFont)
    # set the font for the top level window (and any of its children):
    self.window().setFont(someFont)
    # set the font for *any* widget created in this QApplication:
    QApplication.instance().setFont(someFont)

    # the same as...
    self.pushButton.setStyleSheet(''' font-size: 24px; ''')
    # etc...

Also, consider setting the Qt.AA_UseStyleSheetPropagationInWidgetStyles attribute for the application instance.

Setting and inheritance

By default, Qt uses font propagation (as much as palette propagation) for both setFont and setStyleSheet, but whenever a style sheet is set, it takes precedence, even if it's set on any of the parent widgets (up to the top level window OR the QApplication instance).

Whenever stylesheets are applied, there are various possibilities, based on CSS Selectors:

  • 'font-size: 24px;': no selector, the current widget and any of its child will use the specified font size;
  • 'QClass { font-size: 24px; }': classes and subclasses selector, any widget (including the current instance) and its children of the same class/subclass will use the specified font size:
  • 'QClass[property="value"] {...}': property selector, as the above, but only if the property matches the value; note that values are always quoted, and bool values are always lower case;
  • '.QClass {...}': classes selector, but not subclasses: if you're using a subclass of QLabel and the stylesheet is set for .QLabel, that stylesheet won't be applied;
  • 'QClass#objectName {...}': apply only for widgets for which objectName() matches;
  • 'QParentClass QClass {...}': apply for widget of class QClass that are children of QParentClass
  • 'QParentClass > QClass {...}': apply for widget of class QClass that are direct children of QParentClass

Note that both setFont and setStyleSheet support propagation, but setStyle only works on children when set to the QApplication instance: if you use widget.setStyle() it won't have effect on any of the widget's children.

Finally, remember:

  • whenever a widget gets reparented, it receives the font, palette and stylesheet of its parent, in "cascading" mode (the closest parent has precedence);
  • stylesheets have precedence on both palette and font, whenever any of the related properties are set, and palette/font properties are not compatible with stylesheets (or, at least, they behave in unexpected ways);
Resuscitate answered 17/8, 2020 at 4:4 Comment(6)
This is a huge help but I have noticed that when using setFont() on rich-text elements the size property does not apply itself...Homebred
@Homebred can you clarify what you mean? Consider that QSS (Qt Style Sheets) are conceptually similar to stylesheets set for Qt rich text, but they don't always work in the same way.Resuscitate
I've just run into an odd scenario in which even plain text labels will not resize. (In Designer) If I create a new label, move it into a layout, and then run the code it works, but if I change its size to the standard font size all my other labels use and then run the code it ignores the size change... All my other labels in multiple layouts use size 10, and if I set any new labels to sizes less then that it works, but if equal to or greater it does not. Changing my layout settings doesn't seem to resolve this either.Homebred
@Homebred Be aware that QLabels do have layout issues, especially if rich text is involved. I'd suggest you to investigate more on the matter, and create a new question with a proper minimal reproducible example.Resuscitate
I will try to discover a little more about my predicament and then post a question showing my findings tomorrow morning under the QT label and link to this.Homebred
The key point for me here was adding the line QCoreApplication.setAttribute(Qt.AA_UseStyleSheetPropagationInWidgetStyles) just after creating the application.Legislature
R
22

To change the font of all QLabels then there are several options:

  • Use Qt StyleSheet

    app.setStyleSheet("QLabel{font-size: 18pt;}")
    
  • Use QApplication::setFont()

    custom_font = QFont()
    custom_font.setWeight(18);
    QApplication.setFont(custom_font, "QLabel")
    
Rigorous answered 16/8, 2020 at 22:43 Comment(3)
Oh, I never noted there's a class specifier to setFont now. When did they add that? Thanks for the addition.Paracelsus
@AdrienLeravat well, it's been there from at least 15-18 years, when there was only Qt3...Resuscitate
@Resuscitate good to know, for some reason I never paid attention to it, or just forgotParacelsus
R
14

While the provided answers should have already given you enough suggestions, I'd like to add some insight.

Are there python sources for Qt?

First of all, you cannot find "the class written in python", because (luckily) there's none. PyQt is a binding: it is an interface to the actual Qt library, which is written in C++.

As you might already know, while Python is pretty fast on nowadays computers, it's not that fast, so using a binding is a very good compromise: it allows the simple syntax Python provides, and gives all speed provided by C++ compiled libraries under the hood.

You can find the source code for Qt widgets here (official mirror), or here.

How to override the default font?

Well, this depends on how you're going to manage your project.

Generally speaking, you can set the default font [size] for a specific widget, for its child widgets, for the top level window or even for the whole application. And there are at least two ways to do it.

  1. use setFont(): it sets the default font for the target; you can get the current default font using something.font(), then use font.setPointSize() (or setPointSizeF() for float values, if the font allows it) and then call setFont(font) on the target.
  2. use font[-*] in the target setStyleSheet();

Target?

The target might be the widget itself, one of its parents or even the QApplication.instance(). You can use both setFont() or setStyleSheet() on any of them:

    font = self.font()
    font.setPointSize(24)
    # set the font for the widget:
    self.pushButton.setFont(someFont)
    # set the font for the top level window (and any of its children):
    self.window().setFont(someFont)
    # set the font for *any* widget created in this QApplication:
    QApplication.instance().setFont(someFont)

    # the same as...
    self.pushButton.setStyleSheet(''' font-size: 24px; ''')
    # etc...

Also, consider setting the Qt.AA_UseStyleSheetPropagationInWidgetStyles attribute for the application instance.

Setting and inheritance

By default, Qt uses font propagation (as much as palette propagation) for both setFont and setStyleSheet, but whenever a style sheet is set, it takes precedence, even if it's set on any of the parent widgets (up to the top level window OR the QApplication instance).

Whenever stylesheets are applied, there are various possibilities, based on CSS Selectors:

  • 'font-size: 24px;': no selector, the current widget and any of its child will use the specified font size;
  • 'QClass { font-size: 24px; }': classes and subclasses selector, any widget (including the current instance) and its children of the same class/subclass will use the specified font size:
  • 'QClass[property="value"] {...}': property selector, as the above, but only if the property matches the value; note that values are always quoted, and bool values are always lower case;
  • '.QClass {...}': classes selector, but not subclasses: if you're using a subclass of QLabel and the stylesheet is set for .QLabel, that stylesheet won't be applied;
  • 'QClass#objectName {...}': apply only for widgets for which objectName() matches;
  • 'QParentClass QClass {...}': apply for widget of class QClass that are children of QParentClass
  • 'QParentClass > QClass {...}': apply for widget of class QClass that are direct children of QParentClass

Note that both setFont and setStyleSheet support propagation, but setStyle only works on children when set to the QApplication instance: if you use widget.setStyle() it won't have effect on any of the widget's children.

Finally, remember:

  • whenever a widget gets reparented, it receives the font, palette and stylesheet of its parent, in "cascading" mode (the closest parent has precedence);
  • stylesheets have precedence on both palette and font, whenever any of the related properties are set, and palette/font properties are not compatible with stylesheets (or, at least, they behave in unexpected ways);
Resuscitate answered 17/8, 2020 at 4:4 Comment(6)
This is a huge help but I have noticed that when using setFont() on rich-text elements the size property does not apply itself...Homebred
@Homebred can you clarify what you mean? Consider that QSS (Qt Style Sheets) are conceptually similar to stylesheets set for Qt rich text, but they don't always work in the same way.Resuscitate
I've just run into an odd scenario in which even plain text labels will not resize. (In Designer) If I create a new label, move it into a layout, and then run the code it works, but if I change its size to the standard font size all my other labels use and then run the code it ignores the size change... All my other labels in multiple layouts use size 10, and if I set any new labels to sizes less then that it works, but if equal to or greater it does not. Changing my layout settings doesn't seem to resolve this either.Homebred
@Homebred Be aware that QLabels do have layout issues, especially if rich text is involved. I'd suggest you to investigate more on the matter, and create a new question with a proper minimal reproducible example.Resuscitate
I will try to discover a little more about my predicament and then post a question showing my findings tomorrow morning under the QT label and link to this.Homebred
The key point for me here was adding the line QCoreApplication.setAttribute(Qt.AA_UseStyleSheetPropagationInWidgetStyles) just after creating the application.Legislature
M
2

Completing Adrien's answer, you can use QFont class and perform .setFont() method for every button.

my_font = QFont("Times New Roman", 12)
my_button.setFont(my_font)

Using this class you can also change some font parameters, see https://doc.qt.io/qt-5/qfont.html

Yeah, documentation for C++ is okay to read because all methods & classes from C++ are implemented in Python.

UPD: QWidget class also has setFont method so you can set font size on centralwidget as well as using stylesheets.

Mckean answered 16/8, 2020 at 22:39 Comment(0)
P
1

Qt Stylesheets

This is probably the easiest way to do in your situation, you are really trying to apply a specific "style" to all your QLabels. You can apply a style to your whole application, or a specific window, and this will affect all children that match the selectors.

So in your case, to apply to all widgets in your application you can do the following to set the font size of all QLabel instances:

  app = QApplication([])
  app.setStyleSheet('.QLabel { font-size: 14pt;}')

Note: Be sure to set the stylesheet before attaching your widgets to its parent, otherwise you would need to manually trigger a style refresh.

Also...

  • The .QLabel selector will only apply to QLabel class instances, and not to classes that inherit QLabel. To apply to both QLabel and inherited classes, use QLabel {...} instead of .QLabel {...} in the stylesheet.

Some documentation to help you beyond that:

Paracelsus answered 16/8, 2020 at 22:30 Comment(4)
Note: using the . selector means that QLabel subclasses will not use that stylesheet.Resuscitate
Sorry, but still not completely correct. QMainWindow is a QWidget subclass, meaning that it does support both stylesheets and their cascading behavior. While it usually has no direct painting (because it normally paints almost anything), it does submit to stylesheets set to it (directly and not). First of all, you can set the stylesheet for any child widgets. Then it also supports basic stylesheet properties, such as font[-*], color, background[-color] or border[-*]: even without overriding the paintEvent, you can clearly see that the border and background are actually applied.Resuscitate
Also, the note about setting the stylesheet before creating widgets is not true. As soon as the widget is added to a parent (including the QApplication) that has some stylesheet set, they will be applied.Resuscitate
@Resuscitate Fixed the QMainWindow, so used to QtQuick now I just mixed both. Regarding setting the stylesheet before, I get your point, it would be more correct to say "attached" instead of "created", as attaching will trigger the restyling.Paracelsus

© 2022 - 2024 — McMap. All rights reserved.