Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在QGraphicsItem上添加动画时遇到的一个问题_Python_Pyqt_Pyqt5 - Fatal编程技术网

Python 在QGraphicsItem上添加动画时遇到的一个问题

Python 在QGraphicsItem上添加动画时遇到的一个问题,python,pyqt,pyqt5,Python,Pyqt,Pyqt5,我想在QGraphicsItem上使用QPropertyImation,希望rect项可以从点(100,30)移动到点(100,90)。但是为什么矩形会在窗口的右侧移动呢?x坐标100应使矩形根据场景大小在中间移动 这是我的密码: import sys from PyQt5.QtCore import QPropertyAnimation, QPointF, QRectF from PyQt5.QtWidgets import QApplication, QGraphicsEllipseItem

我想在QGraphicsItem上使用QPropertyImation,希望rect项可以从点(100,30)移动到点(100,90)。但是为什么矩形会在窗口的右侧移动呢?x坐标100应使矩形根据场景大小在中间移动

这是我的密码:

import sys
from PyQt5.QtCore import QPropertyAnimation, QPointF, QRectF
from PyQt5.QtWidgets import QApplication, QGraphicsEllipseItem, QGraphicsScene, QGraphicsView, \
                            QGraphicsObject


class CustomRect(QGraphicsObject):
    def __init__(self):
        super(CustomRect, self).__init__()

    def boundingRect(self):
        return QRectF(100, 30, 100, 30)

    def paint(self, painter, styles, widget=None):
        painter.drawRect(self.boundingRect())


class Demo(QGraphicsView):
    def __init__(self):
        super(Demo, self).__init__()
        self.resize(300, 300)

        self.scene = QGraphicsScene()
        self.scene.setSceneRect(0, 0, 300, 300)

        self.rect = CustomRect()
        self.ellipse = QGraphicsEllipseItem()
        self.ellipse.setRect(100, 180, 100, 50)

        self.scene.addItem(self.rect)
        self.scene.addItem(self.ellipse)

        self.setScene(self.scene)

        self.animation = QPropertyAnimation(self.rect, b'pos')
        self.animation.setDuration(1000)
        self.animation.setStartValue(QPointF(100, 30))
        self.animation.setEndValue(QPointF(100, 90))
        self.animation.setLoopCount(-1)
        self.animation.start()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())
任何帮助都将不胜感激。

试试:

import sys
from PyQt5.QtCore import QPropertyAnimation, QPointF, QRectF
from PyQt5.QtWidgets import QApplication, QGraphicsEllipseItem, QGraphicsScene, QGraphicsView, \
                            QGraphicsObject


class CustomRect(QGraphicsObject):
    def __init__(self):
        super(CustomRect, self).__init__()

    def boundingRect(self):
#        return QRectF(100, 30, 100, 30)
        return QRectF(0, 0, 100, 30)                          # +++

    def paint(self, painter, styles, widget=None):
        painter.drawRect(self.boundingRect())


class Demo(QGraphicsView):
    def __init__(self):
        super(Demo, self).__init__()
        self.resize(300, 300)

        self.scene = QGraphicsScene()
        self.scene.setSceneRect(0, 0, 300, 300)

        self.rect = CustomRect()
        self.ellipse = QGraphicsEllipseItem()
        self.ellipse.setRect(100, 180, 100, 50)

        self.scene.addItem(self.rect)
        self.scene.addItem(self.ellipse)

        self.setScene(self.scene)

        self.animation = QPropertyAnimation(self.rect, b'pos')
        self.animation.setDuration(3000)
        self.animation.setStartValue(QPointF(100, 30))
        self.animation.setEndValue(QPointF(100, 90))
        self.animation.setLoopCount(-1)
        self.animation.start()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

看来他们不知道地球的不同坐标系

在该系统中,至少有以下坐标系:

  • 窗口(viewport())的坐标系,其中(0,0)始终位于窗口的左上角

  • 场景的坐标系,这是相对于某个预先建立的点

  • 每个项目的坐标系,该坐标系由paint()方法用于绘制,boundingRect()和shape()方法用于获取项目的边

你还必须有另一个概念,一个项目的位置是相对于父项目的,如果他有,如果他没有,它是相对于场景的

类比

为了解释不同的坐标系,我使用了使用相机记录场景的类比

  • QGraphicsView就是摄像机的屏幕
  • QGraphicscene是记录的场景,因此点(0,0)是一些方便的点
  • <> LQ>是场景的元素,它们的位置可以相对于其他项目或场景,例如,我们可以考虑演员的鞋相对于演员的位置,或者项目可以是同一演员。

基于以上,我将解释发生了什么,我们将给出几个解决方案


rect项没有父项,默认情况下,项的位置图标为(0,0),因此此时项的坐标系与场景重合,因此boundingRect将直观地定义位置,并且当您放置QRectF(100,30,100,30)时,将在该位置绘制,该位置在场景中重合相同。但是,当应用动画时,首先要做的是将项目的位置设置为(100,30),这样,由于场景和项目的坐标系不匹配,一个从另一个移动,因此boundingRect不再匹配场景的QRectF(100,30,100,30),而是以相同的因子移动(仅因为存在位移,所以没有缩放或旋转),矩形将为QRectF(200、60、100、30),并且相对于始终在QRect中的椭圆(100、180、100、50)矩形从200>100开始在右边,从60开始向上谢谢@eyllanesc,你的回答和往常一样好。那么你的意思是动画是基于项目的坐标而不是场景的坐标吗?我实际上知道如何解决这个问题,但就是不理解动画使用的坐标。@很高兴我没有这么说,我所做的是什么所说的是视觉观察是一组变换的结果。我想,为了简化事物,必然的结论必须总是从(0,0)开始。因为这是相对于同一项目的坐标系的,因为这避免了复杂的计算,这在我的第一个解决方案中很明显。@很高兴动画不知道或对了解不同类型的坐标系感兴趣,它只修改属性“pos”。在本例中,pos是关于场景的,但您的项目绘制在一个矩形上,该矩形已在自身上移位
QRectF(100,30,100,30)
,and@just_be_happy[cont.]您还可以将其相对于场景移动:QPointF(100,30)在动画结束后的一段时间内,图形从QRectF+(100,30)移动(100,30)QPoint的值=(200,60),因此它位于椭圆(100,180,100,50)的右侧和上方。只需始终使用QRectF(0,0,w,h)实现boundingRect并使用setPos移动它。我认为如果boundingRect是(100,30,100,30),并且如果我想让rect在右侧移动,我需要使用QPointF(200,30)和QPointF(200,90)。我不知道有位移。谢谢你。我会把你的答案标记为正确。但为什么会有位移?