【问题标题】:Using QVariantAnimation to show a list of images使用 QVariantAnimation 显示图像列表
【发布时间】:2019-05-22 00:33:29
【问题描述】:

我在使用 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 过去给他们的起点和终点。

【问题讨论】:

  • 我猜你指向的是 QGraphicsView 中的 QGraphicsPixmapItem。我说的对吗?
  • 是的,我在场景中使用 QGraphicsPixmapItem。

标签: python pyqt pyqt5


【解决方案1】:

有几种方法可以实现你指出的(距离很小,所以我改变了尺寸)。

  • 每个部分的这个方法是一个 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_())

【讨论】:

  • 如果我使用 Key 信号实现这一点,我应该能够在动画循环播放时按下一个键,然后再按下另一个键吗?它会中断循环然后播放另一个动画吗?
  • @BlackMage 这取决于你想做什么,你可以用 stop 停止动画。
  • 另外,QPointF 是您与实际位置相加的距离吗?因为当我用 X 和 Y 中的某物更改点时,但使用相同的 Y,我认为它会在 Y 的相同位置前进但穿过 X。但它不会像那样移动。
  • @BlackMage QPointF 是一个存储坐标的类。另一方面,我无法指出任何内容,因为我不了解您,请提供minimal reproducible example
  • 我将 QPointF 分别更改为 (40, 20) - (80, 20) - (120, 20),它像曲线一样移动。
猜你喜欢
  • 1970-01-01
  • 2014-07-03
  • 1970-01-01
  • 2013-06-06
  • 2020-05-10
  • 1970-01-01
  • 1970-01-01
  • 2012-01-18
  • 2020-10-27
相关资源
最近更新 更多