2

I wanted to ask if we could just animate the fontsize of the QLabel in PyQt5 with QPropertyAnimation.

I tried by adding QPropertyAnimation(self.label , b"fontSize") but It was not working and I got the warning

I want you increase the text of the QLabel and then again switch to normal size

TheFishTheySay
  • 190
  • 2
  • 17
  • 1
    Hello and welcome to StackOverflow. Please consider to always provide detailed information when asking question (take your time to read [ask] good questions): "it was not working" is not really useful to us, but you could show us what you actually tried. Also, to what warning are you referring to? – musicamante Jun 25 '21 at 11:54
  • 1
    I wrote.. See in second paragraph. – TheFishTheySay Jun 25 '21 at 12:24
  • 1
    Im referring to this warning: Trying to animate a non property animation – TheFishTheySay Jun 25 '21 at 12:25

1 Answers1

2

From the QPropertyAnimation description:

QPropertyAnimation interpolates over Qt properties. As property values are stored in QVariants, the class inherits QVariantAnimation, and supports animation of the same meta types as its super class.

A class declaring properties must be a QObject. To make it possible to animate a property, it must provide a setter (so that QPropertyAnimation can set the property's value).

All classes that inherit from QObject (including widgets) support Qt properties, and in fact most of them have "builtin" properties, but, obviously, not all properties support animations: they must be based on numeric values. You can animate a numeric change (eg: from 0 to 100), not a text (eg. from 'ABC' to 'PYZ').

For instance, all QWidget have a pos property, and since such property (which is a QPoint) is based on numbers, you can create an animation. You can see the list of supported variant types for animations in the QVariantAnimation docs. Consider that all documentation pages regarding QObject subclasses contain a property section (see the QWidget properties for example), and that properties obviously are inherited from their super classes.

There is no property for the font size, though, so there are two possibilities:

  1. create a custom property (by using the pyqtProperty decorator in PyQt);
  2. use a QVariantAnimation, which is not bound to any property;

Depending on the situation, one might prefer one approach or the other, but for this specific case it doesn't change that much; the QVariantAnimation is certainly simpler, the Qt property approach is more "compliant".

Here you can see how the property is created using the pyqtProperty decorator. Since the animation writes the property, having a setter is mandatory.

class AnimationTest(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.startButton = QtWidgets.QPushButton('Start')
        self.label = QtWidgets.QLabel('Hello!')
        self.labelFont = self.font()
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.startButton)
        layout.addWidget(self.label)

        self.ani = QtCore.QPropertyAnimation(self, b'labelFontSize')
        self.ani.setStartValue(10)
        self.ani.setEndValue(80)
        self.ani.setDuration(1500)

        self.startButton.clicked.connect(self.ani.start)

    @QtCore.pyqtProperty(int)
    def labelFontSize(self):
        return self.labelFont.pointSize()

    @labelFontSize.setter
    def labelFontSize(self, size):
        self.labelFont.setPointSize(size)
        self.label.setFont(self.labelFont)


import sys
app = QtWidgets.QApplication(sys.argv)
test = AnimationTest()
test.show()
sys.exit(app.exec_())

The variant animation is certainly shorter:

class AnimationTest(QtWidgets.QWidget):
    def __init__(self):
        # ...
        self.ani = QtCore.QVariantAnimation()
        self.ani.setStartValue(10)
        self.ani.setEndValue(80)
        self.ani.setDuration(1500)
        self.ani.valueChanged.connect(self.updateLabelFont)

        self.startButton.clicked.connect(self.ani.start)

    def updateLabelFont(self, value):
        self.labelFont.setPointSize(value)
        self.label.setFont(self.labelFont)

Please consider that font size animations are often problematic, as most fonts have slightly different glyphs and spacings depending on the size. In the examples above I used a pretty long animation that will probably show the effect: while the size increases linearly, the change in the font usually is not very smooth.

musicamante
  • 41,230
  • 6
  • 33
  • 58
  • Thanks for your answer, I will check if this code runs – TheFishTheySay Jun 26 '21 at 02:09
  • 1
    @0xsapphir3 you're welcome, but please consider that you should first try if the solution of an answer *does* solve your problem before setting it as accepted. – musicamante Jun 26 '21 at 02:11
  • Well, the first code gave me an error but the second work worked. Thanks a lot! :) – TheFishTheySay Jun 26 '21 at 04:47
  • 1
    @0xsapphir3 please remember that StackOverflow is a *community effort*. Saying "it gave me an error" is useless not only to you, but also to anybody else that could be facing a similar problem. What error did you got? Did you implement the code exactly as I suggested? If you got any problem with a provided solution, you should *always* clarify what problem that was: that could be important for *a lot* of people, including those trying to help you. *Common* and *shared* knowledge is very, *very* important. – musicamante Jun 26 '21 at 05:29
  • It was my mistake, I didnt import the pyqtSignal, and thats why i was getting the error. Anyways, I have solved that issue, so thats why i didnt paste the error. – TheFishTheySay Jun 26 '21 at 05:39
  • And BTW, thanks for helping me. I am new to Stack Overflow and my first experience was much better than I thought. I am really grateful to you. – TheFishTheySay Jun 26 '21 at 05:40