【问题标题】:move QGraphicsItem continuously in QGraphicsScene and check Collision在 QGraphicsScene 中连续移动 QGraphicsItem 并检查 Collision
【发布时间】:2019-03-23 17:05:00
【问题描述】:

大约 3 周前,我要求更改 GraphicsScene 中的 GraphicsItem。这是一条线,解决方案是:self.setLine(..)。现在我试着去理解,不断地移动它。所以我有一个 graphicsview gvCanvas 并在一个场景中初始化矩形,线条......它可以工作

为了移动一个矩形,我有下面的 Class 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()

然后我尝试在矩形周围移动

    xm =20
    ym = 20
    for i in range(1,5):
        time.sleep(0.8)
        print("nachsleep",i)
        self.rect2.movemyRect(xm, ym, 10)
        myyrs = QtWidgets.QGraphicsRectItem.rect(self.rect2)
        self.rect2.setRect(myyrs)
        self.scene.update()
        listtreffer = self.scene.collidingItems(self.lnk, mode=Qt.IntersectsItemShape)
        for treffer in listtreffer:
            print("treffer", treffer)

循环有效,但移动和旋转的矩形仅在我的场景循环结束时发生变化,而不是在每一步之后。我认为,使用“setRect ...”语句,它应该在每次遍历循环时都起作用。此外,scene.update() 也无济于事。

如果我不使用循环,它也可以。

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

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

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

(我也尝试对动画和 QPropertyAnimantion 做同样的事情。我无法触发或运行高级语句。检查碰撞,即使在移动时也是如此。但我认为,为此我应该打开一个新问题)

【问题讨论】:

    标签: python pyqt5 qgraphicsscene qgraphicsitem


    【解决方案1】:

    在 GUI 中,您永远不应该使用 time.sleep,因为它会阻塞事件循环,因此窗口会冻结,从而阻止重新绘制 GUI。在 Qt 中,您必须使用事件执行操作,例如在以下代码中,每次触发计时器时,更改位置。使用 QVariantAnimation 进行平滑移动,不能使用 QPropertyAnimation,因为 QGraphicsItem 不是 QObjects 并且位置不是 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_())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-06
      • 2015-11-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-27
      • 1970-01-01
      • 2013-10-13
      相关资源
      最近更新 更多