本文通过Python3+PyQt5实现《python Qt Gui 快速编程》这本书的千足蛇动画程序,采用QGraphicsView,QGraphicsScene,QGraphicsItem,这个程序包含有多个文本,图片和框的页面。有些图形类在PyQt5已过时,所以本代码改动幅度比较大。本文实现复杂形状动画内容,一种通过项自身定时器,另一种采用窗口超时处理程序来实现项目移动碰撞等功能。
1,通过自身定时器实现,完整代码如下:
#!/usr/bin/env python3
import math
import random
import sys
from PyQt5.QtCore import (QTimer, QPointF, QRectF, Qt)
from PyQt5.QtWidgets import (QApplication, QDialog,
QGraphicsItem, QGraphicsScene, QGraphicsView, QHBoxLayout,
QPushButton, QSlider,QVBoxLayout)
from PyQt5.QtGui import (QBrush, QColor,QPainter,QPainterPath,QPolygonF)
SCENESIZE = 500
INTERVAL = 1
class Head(QGraphicsItem):
Rect = QRectF(-30, -20, 60, 40)
def __init__(self, color, angle, position):
super(Head, self).__init__()
self.color = color
self.angle = angle
self.setPos(position)
def boundingRect(self):
return Head.Rect
def shape(self):
path = QPainterPath()
path.addEllipse(Head.Rect)
return path
def paint(self, painter, option, widget=None):
painter.setPen(Qt.NoPen)
painter.setBrush(QBrush(self.color))
painter.drawEllipse(Head.Rect)
if option.levelOfDetailFromTransform(self.transform()) > 0.5: # Outer eyes
painter.setBrush(QBrush(Qt.yellow))
painter.drawEllipse(-12, -19, 8, 8)
painter.drawEllipse(-12, 11, 8, 8)
if option.levelOfDetailFromTransform(self.transform())> 0.8: # Inner eyes
painter.setBrush(QBrush(Qt.darkBlue))
painter.drawEllipse(-12, -19, 4, 4)
painter.drawEllipse(-12, 11, 4, 4)
if option.levelOfDetailFromTransform(self.transform()) > 0.9: # Nostrils
painter.setBrush(QBrush(Qt.white))
painter.drawEllipse(-27, -5, 2, 2)
painter.drawEllipse(-27, 3, 2, 2)
def advance(self, phase):
if phase == 0:
angle = self.angle
while True:
flipper = 1
angle += random.random() * random.choice((-1, 1))
offset = flipper * random.random()
x = self.x() + (offset * math.sin(math.radians(angle)))
y = self.y() + (offset * math.cos(math.radians(angle)))
if 0 <= x <= SCENESIZE and 0 <= y <= SCENESIZE:
break
else:
flipper = -1 if flipper == 1 else 1
self.angle = angle
self.position = QPointF(x, y)
else:
self.setRotation(random.random() * random.choice((-1, 1)))
self.setPos(self.position)
if self.scene():
for item in self.scene().collidingItems(self):
if isinstance(item, Head):
self.color.setRed(min(255, self.color.red() + 1))
else:
item.color.setBlue(min(