为 size 属性设置动画时从中心调整小部件的大小 [英] Resize widget from center when animating the size property

查看:69
本文介绍了为 size 属性设置动画时从中心调整小部件的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个小部件,该小部件在鼠标悬停时会略微增大,并在鼠标再次离开时减小.
到目前为止,这是我想出的:

I'm trying to code a widget that slightly increases in size on mouse-over and decreases when the mouse leaves again.
This is what I have come up with so far:

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

from random import randrange


class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setFixedSize(500, 500)

        cent_widget = QWidget()
        self.setCentralWidget(cent_widget)

        layout = QVBoxLayout()
        cent_widget.setLayout(layout)

        layout.addWidget(MyItem(), Qt.AlignCenter,
                         alignment=Qt.AlignCenter)


class MyItem(QLabel):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setBaseSize(200, 250)
        self.setMinimumSize(self.baseSize())
        self.resize(self.baseSize())

        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

        self.setStyleSheet('background: #{:02x}{:02x}{:02x}'.format(
            randrange(255), randrange(255), randrange(255)
        ))

        # Animation
        self._enlarged = False
        self.zoom_factor = 1.2

        self.anim = QPropertyAnimation(self, b'size')
        self.anim.setEasingCurve(QEasingCurve.InOutSine)
        self.anim.setDuration(250)

    def enterEvent(self, event: QEvent) -> None:
        self.resize_anim()
        self._enlarged = True

    def leaveEvent(self, event: QEvent) -> None:
        self.resize_anim()
        self._enlarged = False

    def resize_anim(self):
        if self._enlarged:
            new_size = self.baseSize()
        else:
            new_size = QSize(
                int(self.baseSize().width() * self.zoom_factor),
                int(self.baseSize().height() * self.zoom_factor)
            )
        self.anim.setEndValue(new_size)
        self.anim.start()


if __name__ == '__main__':
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

它几乎按照我想要的方式工作,我唯一的问题是小部件从左上角而不是从中心调整大小.
我该如何改变?

It's almost working the way I want, my only problem is that the widget gets resized from the top-left corner instead of from the center.
How can I change that?

推荐答案

您应该使用几何属性而不是使用 size 属性进行动画处理,因为它是相对于父小部件的,因此您可以对其几何进行动画处理,使中心保持不变.

Instead of animating using the size property you should use the geometry property as it is relative to the parent widget, so you can animate its geometry making the center remain invariant.

from PyQt5.QtCore import (
    QAbstractAnimation,
    QEasingCurve,
    QEvent,
    QPropertyAnimation,
    QRect,
    Qt,
)
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import (
    QApplication,
    QLabel,
    QMainWindow,
    QSizePolicy,
    QVBoxLayout,
    QWidget,
)

import random


class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setFixedSize(500, 500)

        cent_widget = QWidget()
        self.setCentralWidget(cent_widget)

        layout = QVBoxLayout(cent_widget)
        layout.addWidget(MyItem(), alignment=Qt.AlignCenter)


class MyItem(QLabel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setBaseSize(200, 250)
        self.setMinimumSize(self.baseSize())
        self.resize(self.baseSize())

        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

        self.setStyleSheet(
            "background: {}".format(QColor(*random.sample(range(255), 3)).name())
        )

        # Animation
        self.zoom_factor = 1.2

        self.anim = QPropertyAnimation(self, b"geometry")
        self.anim.setEasingCurve(QEasingCurve.InOutSine)
        self.anim.setDuration(250)

    def enterEvent(self, event: QEvent) -> None:

        initial_rect = self.geometry()
        final_rect = QRect(
            0,
            0,
            int(initial_rect.width() * self.zoom_factor),
            int(initial_rect.height() * self.zoom_factor),
        )
        final_rect.moveCenter(initial_rect.center())

        self.anim.setStartValue(initial_rect)
        self.anim.setEndValue(final_rect)
        self.anim.setDirection(QAbstractAnimation.Forward)
        self.anim.start()

    def leaveEvent(self, event: QEvent) -> None:
        self.anim.setDirection(QAbstractAnimation.Backward)
        self.anim.start()


if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

这篇关于为 size 属性设置动画时从中心调整小部件的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆