所以我試圖學習PyQt中的動畫以及我可以在網上找到的所有例子,他們似乎都使用self.update()
或self.repaint()
方法來增加動畫。這意味着基本上,代碼必須擦除然後重新繪製每個幀的整個小部件,即使我打算製作動畫的很多部分都是靜態的。PyQt - 動畫沒有重繪一切?
例如下面的代碼,這會生成一個循環進度餅圖。重要的一點是ProgressMeter
(第一類)下的paint()
方法:對於動畫中的每個幀,此示例都繪製背景,實際進度餅圖和百分比指示符。
如果我的代碼更改爲類似:
if self.angle > 120:
# do not draw background
再經過120幀,背景不拿得出了。
這似乎非常低效,因爲(邏輯上)背景只能繪製一次,不是嗎?
對於這些動畫,你會推薦什麼?
附錄:我在這個網站上偷了很多東西來竊取示例和代碼,但是很久沒有發佈了。如果我沒有正確遵守,請告訴我適當的禮節等。
import sys
from PyQt4 import QtGui, QtCore
class ProgressMeter(QtGui.QGraphicsItem):
def __init__(self, parent):
super(ProgressMeter, self).__init__()
self.parent = parent
self.angle = 0
self.per = 0
def boundingRect(self):
return QtCore.QRectF(0, 0, self.parent.width(),
self.parent.height())
def increment(self):
self.angle += 1
self.per = int(self.angle/3.6)
if self.angle > 360:
return False
else:
return True
def paint(self, painter, option, widget):
self.drawBackground(painter, widget)
self.drawMeter(painter, widget)
self.drawText(painter)
def drawBackground(self, painter, widget):
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(QtCore.Qt.NoPen)
p1 = QtCore.QPointF(80, 80)
g = QtGui.QRadialGradient(p1 * 0.2, 80 * 1.1)
g.setColorAt(0.0, widget.palette().light().color())
g.setColorAt(1.0, widget.palette().dark().color())
painter.setBrush(g)
painter.drawEllipse(0, 0, 80, 80)
p2 = QtCore.QPointF(40, 40)
g = QtGui.QRadialGradient(p2, 70 * 1.3)
g.setColorAt(0.0, widget.palette().midlight().color())
g.setColorAt(1.0, widget.palette().dark().color())
painter.setBrush(g)
painter.drawEllipse(7.5, 7.5, 65, 65)
def drawMeter(self, painter, widget):
painter.setPen(QtCore.Qt.NoPen)
painter.setBrush(widget.palette().highlight().color())
painter.drawPie(7.5, 7.5, 65, 65, 0, -self.angle * 16)
def drawText(self, painter):
text = "%d%%" % self.per
font = painter.font()
font.setPixelSize(11)
painter.setFont(font)
brush = QtGui.QBrush(QtGui.QColor("#000000"))
pen = QtGui.QPen(brush, 1)
painter.setPen(pen)
# size = painter.fontMetrics().size(QtCore.Qt.TextSingleLine, text)
painter.drawText(0, 0, 80, 80,
QtCore.Qt.AlignCenter, text)
class MyView(QtGui.QGraphicsView):
def __init__(self):
super(MyView, self).__init__()
self.initView()
self.setupScene()
self.setupAnimation()
self.setGeometry(300, 150, 250, 250)
def initView(self):
self.setWindowTitle("Progress meter")
self.setRenderHint(QtGui.QPainter.Antialiasing)
policy = QtCore.Qt.ScrollBarAlwaysOff
self.setVerticalScrollBarPolicy(policy)
self.setHorizontalScrollBarPolicy(policy)
self.setBackgroundBrush(self.palette().window())
self.pm = ProgressMeter(self)
self.pm.setPos(55, 55)
def setupScene(self):
self.scene = QtGui.QGraphicsScene(self)
self.scene.setSceneRect(0, 0, 250, 250)
self.scene.addItem(self.pm)
self.setScene(self.scene)
def setupAnimation(self):
self.timer = QtCore.QTimeLine()
self.timer.setLoopCount(0)
self.timer.setFrameRange(0, 100)
self.animation = QtGui.QGraphicsItemAnimation()
self.animation.setItem(self.pm)
self.animation.setTimeLine(self.timer)
self.timer.frameChanged[int].connect(self.doStep)
self.timer.start()
def doStep(self, i):
if not self.pm.increment():
self.timer.stop()
self.pm.update()
app = QtGui.QApplication([])
view = MyView()
view.show()
sys.exit(app.exec_())
謝謝!那個文檔就是我之前看到的提示這個問題的東西。問題就像它說的那樣,兩種方法都會擦除然後重新繪製整個小部件,但我真的不需要這樣做,因爲只有所有對象中的一小部分需要更改。例如在Tkinter中(我正在從GUI遷移GUI),我可以創建一個畫布,但只需使用self.object.move()方法只移動我需要的動畫。再次感謝! – user3627191
@ user3627191不客氣,但你沒有把答案標記爲已接受,還有什麼還不清楚嗎? – BPL
我的壞 - upvoted,但沒有意識到我需要點擊複選標記以及:) – user3627191