python - 在 QGraphicsScene 中移动 QGraphicItems 的有效方法

标签 python pyqt pyqt5 qgraphicsview qgraphicsscene

我正在使用 pyqt5 开发视频播放器。我在场景中使用 QGraphicsVideoItem。在此视频项目之上,我还需要一些在每个新帧上围绕场景移动的多边形。他们跟踪视频中的内容。理想情况下我不想让它们以 30 fps 的速度移动。我进行了一次测试运行,以 30 fps 的速度将 1 个多边形移动 1 个像素。我使用 QGraphicsPolygonItem 中的 setPos() 函数完成此操作。这是可行的,但它非常不稳定,每次多边形在重新绘制之前都可以看到它闪烁白色。我认为发生这种情况是因为我移动得太快了。此外,此操作在线程中并行运行。

我想知道的是,当您打开“QGraphicsItem.ItemIsSelectable”和“QGraphicsItem.ItemIsMovable”标志并手动移动项目时,是否有一种方法可以像移动多边形一样移动多边形。这是非常顺利的,也是我想要实现的。

我还尝试将点保持静止,而不是移动 QGraphicsVideoitem,这有点有效(移动更稳定并且没有闪烁的白色),但我无法让场景以 videoItem 为中心。我尝试使用“setFocus”,但这不起作用。

谢谢。

最佳答案

在这些情况下,不建议逐像素移动每帧中的项目,最好每 n 帧移动一次,以便移动平滑,因为必须对路线进行插值,因为可以使用 QVariantAnimation,在以下示例每 300 毫秒随机生成一次多边形。

import random
from PyQt5 import QtCore, QtGui, QtWidgets

class GraphicsPolygonItem(QtWidgets.QGraphicsPolygonItem):
    def moveTo(self, next_pos, duration=250):
        self._animation = QtCore.QVariantAnimation(
            duration = duration,
            valueChanged = self.setPos,
            startValue = self.pos(),
            endValue = next_pos)
        self._animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)

class GraphicsView(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        super(GraphicsView, self).__init__(parent)
        _scene = QtWidgets.QGraphicsScene(QtCore.QRectF(-250, -250, 500, 500), self)
        self.setScene(_scene)
        self.scene().addRect(self.sceneRect(), brush=QtGui.QBrush(QtCore.Qt.green))
        polygon = QtGui.QPolygonF()
        polygon << QtCore.QPointF( 10, 10 ) << QtCore.QPointF( 0, 90 ) \
                << QtCore.QPointF( 40, 70 ) << QtCore.QPointF( 80, 110 ) \
                << QtCore.QPointF( 70, 20 )

        self._interval = 300

        self.poly_item = GraphicsPolygonItem(polygon)
        self.poly_item.setBrush(QtGui.QBrush(QtCore.Qt.red))
        self.scene().addItem(self.poly_item)
        timer = QtCore.QTimer(self, interval=self._interval, timeout=self.on_timeout)
        timer.start()

    def on_timeout(self):
        p = QtCore.QPointF(
            random.randint(self.sceneRect().left(), self.sceneRect().right()), 
            random.randint(self.sceneRect().top(), self.sceneRect().bottom()))
        self.poly_item.moveTo(p, self._interval)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = GraphicsView()
    w.resize(720, 720)
    w.show()
    sys.exit(app.exec_())

关于python - 在 QGraphicsScene 中移动 QGraphicItems 的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53807573/

相关文章:

python - pyQt5:无法连接 QSpinBox::valueChanged(int)

c++ - c++ 和 python 中的算法相同但输出不同

python - 如何在 Pandas 中的两列上使用聚合函数而不弄乱索引?

PyQtGraph:如何捕捉绘图范围变化?

python - PyOpenGL: glDrawArrays() - WindowsError: 异常: 访问冲突读取 0x0000000000000000

python - QFileDialog - PyQt4/PyQt5/PySide 之间的区别

python - 将多个列表连接在一行中,不使用括号或引号

python - Pandas 在多个层面上融化

python - 在 QDialog 中显示子进程的实时输出

python - 移动项目时,QStandardItem 无法正确克隆