所以我想制作一个动画,作为Waze应用程序中的箭头,我希望它移动得平滑和恒定。我不知道在QtGraphicsView中怎么做。我的对象(箭头)按QVariantAnimation移动,它从当前位置插值到下一个位置。稍微停一下就结束了。我不想要这个功能(停止),我想让我的动画连续和流畅地运行。有人知道是怎么回事吗?
下面是一个最小的可重现的例子:
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
import sys
import random
random.seed(0)
class Example(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.button = QtWidgets.QPushButton("Start", self)
self.button.clicked.connect(self.doAnim)
self.button.move(10, 10)
self.scene = QtWidgets.QGraphicsScene()
self.view = QtWidgets.QGraphicsView(self)
self.view.setScene(self.scene)
self.view.setGeometry(150, 30, 500, 800)
self.setGeometry(300, 300, 380, 300)
self.setWindowTitle('Animation')
pen = QtGui.QPen()
pen.setBrush(QtGui.QBrush(QtCore.Qt.darkBlue))
pen.setWidth(5)
self.scene.addEllipse(0,0,10,10, pen)
self.show()
self.ellipse = self.scene.items()[0]
def doAnim(self):
# Every time that I click on the start buttom this animation runs
# and stops,
pos = self.ellipse.pos()
new_pos = QtCore.QPointF(pos.x()+ random.randint(-10, 10), pos.y() +random.randint(-10, 10))
self.anim = QtCore.QVariantAnimation()
self.anim.setDuration(1000)
self.anim.setStartValue(pos)
self.anim.setEndValue(new_pos)
self.anim.setLoopCount(-1)
self.anim.valueChanged.connect(self.ellipse.setPos)
self.anim.start(QtCore.QVariantAnimation.DeleteWhenStopped)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()发布于 2021-01-19 02:47:14
简单的解决方案是连接到动画的finished信号,如果有新的目标位置可用,则再次设置开始/结束值。
from random import randrange
from PyQt5 import QtCore, QtGui, QtWidgets
class Example(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
layout = QtWidgets.QGridLayout(self)
self.startButton = QtWidgets.QPushButton("Start")
layout.addWidget(self.startButton)
self.addPointButton = QtWidgets.QPushButton("Add target point")
layout.addWidget(self.addPointButton, 0, 1)
self.view = QtWidgets.QGraphicsView()
layout.addWidget(self.view, 1, 0, 1, 2)
self.scene = QtWidgets.QGraphicsScene()
self.view.setScene(self.scene)
self.scene.setSceneRect(-10, -10, 640, 480)
pen = QtGui.QPen(QtCore.Qt.darkBlue, 5)
self.ellipse = self.scene.addEllipse(0, 0, 10, 10, pen)
self.queue = []
self.startButton.clicked.connect(self.begin)
self.addPointButton.clicked.connect(self.addPoint)
self.anim = QtCore.QVariantAnimation()
self.anim.setDuration(1000)
self.anim.valueChanged.connect(self.ellipse.setPos)
self.anim.setStartValue(self.ellipse.pos())
self.anim.finished.connect(self.checkPoint)
def begin(self):
self.startButton.setEnabled(False)
self.addPoint()
def addPoint(self):
self.queue.append(QtCore.QPointF(randrange(600), randrange(400)))
self.checkPoint()
def checkPoint(self):
if not self.anim.state() and self.queue:
if self.anim.currentValue():
# a valid currentValue is only returned when the animation has
# been started at least once
self.anim.setStartValue(self.anim.currentValue())
self.anim.setEndValue(self.queue.pop(0))
self.anim.start()发布于 2021-01-19 02:52:31
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
import sys
import random
import queue
import time
class Position(queue.Queue):
def __init__(self, *args, **kwargs):
super(Position, self).__init__(*args, **kwargs)
class Worker(QtCore.QThread):
pos_signal = QtCore.pyqtSignal(QtCore.QPointF)
def __init__(self, rect, parent=None, *args, **kwargs):
super().__init__(parent)
random.seed(0)
self.pos = QtCore.QPointF(0, 0)
self.rect: QtCore.QRectF = rect
def run(self) -> None:
new_pos = QtCore.QPointF(self.pos.x()+ random.randint(-100, 100), self.pos.y() +random.randint(-100, 100))
if not self.rect.contains(new_pos):
self.run()
else:
self.pos = new_pos
self.pos_signal.emit(new_pos)
time.sleep(0.1)
self.run()
class Example(QtWidgets.QWidget):
next_signal = QtCore.pyqtSignal()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.button = QtWidgets.QPushButton("Start", self)
self.button.clicked.connect(self.doAnim)
self.scene = QtWidgets.QGraphicsScene()
self.view = QtWidgets.QGraphicsView(self)
self.view.setScene(self.scene)
self.view.setGeometry(100, 100, 500, 800)
self.setGeometry(300, 300, 800, 800)
pen = QtGui.QPen()
pen.setBrush(QtGui.QBrush(QtCore.Qt.darkBlue))
pen.setWidth(5)
self.scene.addEllipse(0,0,20,10, pen)
self.ellipse = self.scene.items()[0]
self.rect = QtCore.QRectF(0,0, 200, 200)
self.scene.addRect(self.rect, pen)
self.positions = Position()
self.producer = Worker(rect=self.rect)
self.producer.pos_signal.connect(self.positions.put)
self.producer.start()
self.old = QtCore.QPointF(0, 0)
self.new = None
def ready(self):
self.next_signal.emit()
self.old = self.new
self.doAnim()
def doAnim(self):
# Every time that I click on the start buttom this animation runs
# and stops,
self.sequential_animation = QtCore.QSequentialAnimationGroup(self)
self.new = self.positions.get()
self.anim = QtCore.QVariantAnimation()
self.anim.setDuration(1000)
self.anim.setStartValue(self.old)
self.anim.setEndValue(self.new)
self.anim.valueChanged.connect(self.ellipse.setPos)
self.anim.finished.connect(self.ready)
self.sequential_animation.addAnimation(self.anim)
self.sequential_animation.start(QtCore.QSequentialAnimationGroup.DeleteWhenStopped)
# self.anim.start(QtCore.QVariantAnimation.DeleteWhenStopped)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()https://stackoverflow.com/questions/65776107
复制相似问题