python - 如何为图像/图标小部件设置动画
问题描述
我有一个自定义的“加载”图像,我需要能够在某些动作发生时启动/停止旋转动画。我正在寻找可以向我展示如何执行此操作的代码,但我在 PyQt 中找不到任何特定于旋转的内容。我已经有以下代码,它会导致图像在单击按钮时旋转:
import os
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class myApplication(QWidget):
def __init__(self, parent=None):
super(myApplication, self).__init__(parent)
self.imgPath = os.path.join('path/to/image','image.svg')
pixmap = QPixmap(self.imgPath)
diag = (pixmap.width()**2 + pixmap.height()**2)**0.5
self.label = QLabel()
self.label.setMinimumSize(diag, diag)
self.label.setAlignment(Qt.AlignCenter)
self.label.setPixmap(pixmap)
#---- Prepare a Layout ----
grid = QGridLayout()
button = QPushButton('Rotate 15 degrees')
button.clicked.connect(self.rotate_pixmap)
grid.addWidget(self.label, 0, 0)
grid.addWidget(button, 1, 0)
self.setLayout(grid)
self.rotation = 0
def rotate_pixmap(self):
pixmap = QPixmap(self.imgPath)
self.rotation += 15
transform = QTransform().rotate(self.rotation)
pixmap = pixmap.transformed(transform, Qt.SmoothTransformation)
#---- update label ----
self.label.setPixmap(pixmap)
if __name__ == '__main__':
app = QApplication(sys.argv)
instance = myApplication()
instance.show()
sys.exit(app.exec_())
我发现了这个 C++ 代码,它展示了如何使用QVariantAnimation
and创建旋转动画QTransform
:
class RotateMe : public QLabel {
Q_OBJECT
public:
explicit RotateMe(QWidget* parent = Q_NULLPTR) :
QLabel(parent),
pixmap(100, 100),
animation(new QVariantAnimation )
{
resize(200, 200);
pixmap.fill(Qt::red);
animation->setDuration(10000);
animation->setStartValue(0.0f);
animation->setEndValue(90.0f);
connect(animation, &QVariantAnimation::valueChanged, [=](const QVariant &value){
qDebug()<<value;
QTransform t;
t.rotate(value.toReal());
setPixmap(pixmap.transformed(t));
});
animation->start();
}
private:
QPixmap pixmap;
QVariantAnimation *animation;
};
如何在 python 中重新编写它?我找不到任何显示QVariantAnimation
在 PyQT 中如何使用的示例。
解决方案
逻辑类似于我在下面显示的:
import os
from PyQt5 import QtCore, QtGui, QtWidgets
class RotateMe(QtWidgets.QLabel):
def __init__(self, *args, **kwargs):
super(RotateMe, self).__init__(*args, **kwargs)
self._pixmap = QtGui.QPixmap()
self._animation = QtCore.QVariantAnimation(
self,
startValue=0.0,
endValue=360.0,
duration=1000,
valueChanged=self.on_valueChanged
)
def set_pixmap(self, pixmap):
self._pixmap = pixmap
self.setPixmap(self._pixmap)
def start_animation(self):
if self._animation.state() != QtCore.QAbstractAnimation.Running:
self._animation.start()
@QtCore.pyqtSlot(QtCore.QVariant)
def on_valueChanged(self, value):
t = QtGui.QTransform()
t.rotate(value)
self.setPixmap(self._pixmap.transformed(t))
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
label = RotateMe(alignment=QtCore.Qt.AlignCenter)
img_path = os.path.join('path/to/image','image.svg')
label.set_pixmap(QtGui.QPixmap(img_path))
button = QtWidgets.QPushButton('Rotate')
button.clicked.connect(label.start_animation)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(label)
lay.addWidget(button)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())