在qgraphicscene中连续移动QGraphicsItem并检查冲突

2024-06-30 07:29:50 发布

您现在位置:Python中文网/ 问答频道 /正文

大约3周前,我要求更改graphicscene中的GraphicsItem。这是一条线,解决方案是:自定线(..). 现在我试着去理解,不断地移动它。所以我有一个图形视图gvCanvas在一个场景中初始化矩形,线。。。它起作用了

对于移动rectange,我为类myRect提供了以下代码,其中包含一个__init__和一个movemyrect

class myRect(QtWidgets.QGraphicsRectItem):
    def __init__(self, QRectF):  # *args):
        QtWidgets.QGraphicsRectItem.__init__(self)
        self.setRect(QRectF)
        self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable, True)
        self.setPen(QtGui.QPen(QtCore.Qt.white, 3))

    def movemyRect(self, x, y, angl):
        myyrs = QtWidgets.QGraphicsRectItem.rect(self) #(self.myyr)   #line(items[0])
        ptrr = myyrs.bottomLeft()
        xpos = ptrr.x() + x #+x
        ypos = ptrr.y()  - y
        ptnew=QtCore.QPoint(xpos,ypos)
        myr = QtCore.QRectF(ptnew, QtCore.QSizeF(15,15))
        self.setRotation(angl)
        self.setRect(myr)
        self.update()

然后我试着绕着一个矩形移动

^{pr2}$

循环正常,但移动和旋转的矩形只在场景中循环的末尾发生变化,而不是在每一步之后。我想,有了“setRect…”语句,它应该在每次遍历循环时都有效。还有场景更新()没用。在

如果我不做循环,它也能工作。在

怎么了,移动的矩形并没有出现在循环的每一步上?在

检查碰撞的语句在每一步都是正确的。在

这里还有一个问题:如果我只想检查这个矩形的冲突,那么在类定义中而不是在这个循环中定义一种冲突检查会更好吗?在

(我也尝试对动画和QPropertyAnimantion执行相同的操作。在那里,我无法启动或运行预先声明。检查碰撞,即使是在周围移动时也是有效的。但我想,为此我应该提出一个新的问题)


Tags: selfinitdef场景矩形qtcoreqtwidgetsqrectf
1条回答
网友
1楼 · 发布于 2024-06-30 07:29:50

在图形用户界面中,你不应该使用时间。睡觉因为它会阻止eventloop,因此窗口冻结,从而阻止GUI被重新绘制。在Qt中,您必须使用事件来执行操作,例如在下面的代码中,每次触发计时器时,都要更改位置。要使用QVariantImation平滑移动,不能使用QPropertyImation,因为QGraphicsItem不是QObject,位置也不是qproperty。在

import random
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets

class RectItem(QtWidgets.QGraphicsRectItem):
    def __init__(self, rect=QtCore.QRectF()):
        super(RectItem, self).__init__(rect)
        self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable, True)
        self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges, True)
        self.setPen(QtGui.QPen(QtCore.Qt.red, 3))
        self._pos_animation = QtCore.QVariantAnimation()
        self._pos_animation.valueChanged.connect(self.setPos)

    def move_smooth(self, end, duration=1000):
        if self._pos_animation.state() == QtCore.QAbstractAnimation.Running:
            self._pos_animation.stop()
        self._pos_animation.setDuration(duration)
        self._pos_animation.setStartValue(self.pos())
        self._pos_animation.setEndValue(end)
        self._pos_animation.start()

    def itemChange(self, change, value):
        if change ==QtWidgets.QGraphicsItem.ItemPositionChange:
            color = QtGui.QColor(QtCore.Qt.red)
            if self.scene().collidingItems(self):
                color = QtGui.QColor(QtCore.Qt.green)
            self.setPen(QtGui.QPen(color, 3))
        return super(RectItem, self).itemChange(change, value)

def move_pos(scene):
    for it in scene.items():
        pos = QtCore.QPointF(*random.sample(range(-100, 200), 2))
        if hasattr(it, 'move_smooth'):
            it.move_smooth(pos, 1000)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    app.setStyle('fusion')
    scene = QtWidgets.QGraphicsScene(-100, -100, 200, 200)
    scene.setBackgroundBrush(QtCore.Qt.gray)
    view = QtWidgets.QGraphicsView(scene)
    view.resize(640, 480)
    view.show()
    l = []
    for _ in range(4):
        pos = QtCore.QPointF(*random.sample(range(-100, 200), 2))
        it = RectItem(QtCore.QRectF(-20, -20, 40, 40))
        scene.addItem(it)
        it.setPos(pos)
        l.append(it)
    wrapper = partial(move_pos, scene)
    timer = QtCore.QTimer(interval=3000, timeout=wrapper)
    timer.start()
    wrapper()
    sys.exit(app.exec_())

相关问题 更多 >