在 PyQt5 中动画 QLabel 的 FontSize

Animating FontSize of a QLabel in PyQt5

我想问一下我们是否可以使用 QPropertyAnimation 在 PyQt5 中为 QLabel 的字体大小设置动画。

我尝试添加 QPropertyAnimation(self.label , b"fontSize") 但它不起作用,我收到了警告

我希望你增加 QLabel 的文本,然后再次切换到正常大小

来自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).

所有类继承自 QObject(包括小部件)的都支持 Qt 属性,事实上它们中的大多数都具有“内置”属性,但是,显然,并非所有属性都支持动画:它们必须基于数值。您可以动画化数字变化(例如:从 0 到 100),而不是文本(例如,从 'ABC' 到 'PYZ')。

例如,所有的 QWidget 都有一个 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,例如),并且这些属性显然是从它们的 super 类.

继承的

字体大小没有属性,所以有两种可能:

  1. 创建自定义 属性(使用 PyQt 中的 pyqtProperty 装饰器);
  2. 使用 QVariantAnimation,它不绑定任何 属性;

根据具体情况,人们可能更喜欢一种方法,但对于这种特定情况,它并没有太大改变; QVariantAnimation 当然更简单,Qt 属性 方法更“兼容”。

在这里您可以看到如何使用 pyqtProperty 装饰器创建 属性。由于动画 写入 属性,因此必须具有 setter。

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_())

变体动画肯定更短:

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)

请注意字体大小动画通常会出现问题,因为大多数字体的字形和间距会根据大小略有不同。在上面的例子中我使用了一个很长的动画,可能会显示效果:虽然大小是线性增加的,但字体的变化通常不是很平滑。