首页 > 解决方案 > 使用 QVariantAnimation 显示图像列表

问题描述

我在使用 QVariantAnimation 时遇到了一些麻烦。我一直在寻找如何使用它,但我只是不明白该怎么做。我阅读的文档和示例让我更加困惑。

我有一个 png 图像列表,我希望它们在一定时间内从 A 点移动到 B 点,并根据我定义的步骤更改图像。

例如,A 点为 (0, 0) - B 点为 (6, 0),步长为 (2, 0)。

从 (0, 0) 到 (2, 0) 显示 Image1

从 (2, 0) 到 (4, 0) 显示 Image2

从 (4, 0) 到 (6, 0) 显示 Image3

给出这个例子,因为我不明白 QVariantAnimation 过去给他们的起点和终点。

标签: pythonpyqtpyqt5

解决方案


有几种方法可以实现您指出的内容(距离非常小,所以我更改了尺寸)。

  • 每个部分的这个方法是一个QVariantAnimation,它建立一个新的QPixmap。
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
import random


def create_pixmap():
    pixmap = QtGui.QPixmap(QtCore.QSize(20, 20))
    pixmap.fill(QtGui.QColor(*random.sample(range(255), 3)))
    return pixmap


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.m_scene = QtWidgets.QGraphicsScene(
            QtCore.QRectF(-200, -200, 400, 400), self
        )
        view = QtWidgets.QGraphicsView(self.m_scene)
        self.setCentralWidget(view)

        self.m_pixmap_item = QtWidgets.QGraphicsPixmapItem()
        self.m_scene.addItem(self.m_pixmap_item)

        datas = [
            (QtCore.QPointF(0, 40), create_pixmap()),
            (QtCore.QPointF(0, 80), create_pixmap()),
            (QtCore.QPointF(0, 120), create_pixmap()),
        ]

        self.data_iter = iter(datas)
        self.move()

    def move(self):
        try:
            end_point, pixmap = next(self.data_iter)
            self.m_pixmap_item.setPixmap(pixmap)

            animation = QtCore.QVariantAnimation(
                duration=500,
                valueChanged=self.m_pixmap_item.setPos,
                finished=self.move,
                startValue=self.m_pixmap_item.pos(),
                endValue=end_point,
                parent=self,
            )
            animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)
        except StopIteration:
            pass


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())
  • 在此方法中,itemChange 方法被覆盖,以便它从 QPixmap 更改为每个部分。
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
import random


def create_pixmap():
    pixmap = QtGui.QPixmap(QtCore.QSize(20, 20))
    pixmap.fill(QtGui.QColor(*random.sample(range(255), 3)))
    return pixmap


class GraphicsPixmapItem(QtWidgets.QGraphicsPixmapItem):
    def __init__(self, parent=None):
        super(GraphicsPixmapItem, self).__init__(parent)
        self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges, True)

        self.m_pixmaps = [create_pixmap() for _ in range(3)]

    def itemChange(self, change, value):
        if change == QtWidgets.QGraphicsItem.ItemPositionChange:
            y = self.pos().y()
            if 0 <= y < 40:
                self.change_pixmap(self.m_pixmaps[0])
            elif 40 <= y < 80:
                self.change_pixmap(self.m_pixmaps[1])
            elif 80 <= y < 120:
                self.change_pixmap(self.m_pixmaps[2])
        return super(GraphicsPixmapItem, self).itemChange(change, value)

    def change_pixmap(self, pixmap):
        if self.pixmap() != pixmap:
            self.setPixmap(pixmap)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.m_scene = QtWidgets.QGraphicsScene(
            QtCore.QRectF(-200, -200, 400, 400), self
        )
        view = QtWidgets.QGraphicsView(self.m_scene)
        self.setCentralWidget(view)

        self.m_pixmap_item = GraphicsPixmapItem()
        self.m_scene.addItem(self.m_pixmap_item)

        animation = QtCore.QVariantAnimation(
            duration=3000,
            valueChanged=self.m_pixmap_item.setPos,
            startValue=self.m_pixmap_item.pos(),
            endValue=QtCore.QPointF(0, 120),
            parent=self,
        )
        animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())

推荐阅读