文章目录
- 1 轮换序列的表格
- 2 根据表格轮换图片
- 3 使用QTimer控制动画
- 4 保存动画
- 5 问题处理
- QT Toolbar简单示例
- QT menu简单示例
计划2020年1月18日完成
2小时课时,完成动画设计
- 软件准备
下文中的SVN代码仓,地址为:svn://gitee.com/bigearrabbit/kevinpython/kevinanimation
1 轮换序列的表格
SVN代码仓切换到版本6。
- 表格设计
按照30度一个图片,360/30 = 12个图片。
每行为一个时间的状态,时间间隔为50毫秒
每列为一个位置的颜色饱和度
保存为文件 loop.xlsx
ms | Cir 0 | Cir 1 | Cir 2 | Cir 3 | Cir 4 | Cir 5 | Cir 6 | Cir 7 | Cir 8 | Cir 9 | Cir 10 | Cir 11 |
Green | Green | Green | Green | Green | Green | Green | Green | Green | Green | Green | Green | |
0 | 100 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
50 | 90 | 100 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
100 | 80 | 90 | 100 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
150 | 70 | 80 | 90 | 100 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
200 | 60 | 70 | 80 | 90 | 100 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
250 | 50 | 60 | 70 | 80 | 90 | 100 | 0 | 0 | 0 | 0 | 0 | 0 |
300 | 40 | 50 | 60 | 70 | 80 | 90 | 100 | 0 | 0 | 0 | 0 | 0 |
350 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100 | 0 | 0 | 0 | 0 |
400 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100 | 0 | 0 | 0 |
450 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100 | 0 | 0 |
500 | 0 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100 | 0 |
…
- 添加xlrd引用:
import xlrd
添加变量初始化:
self.LoopTable = []
self.LoopIndex = 0
- 创建读取表格函数:
def readExcelTable(self, iFilePath):
# 打开文件:
wb = xlrd.open_workbook(iFilePath)
sheetCount = len(wb.sheets()) # sheet数量
if sheetCount < 1:
return []
sheet = wb.sheet_by_index(0) # sheet索引从0开始
if sheet.nrows < 1 or sheet.ncols < 1:
return []
contents = [] # 定义一个行数组
# 逐行读取
for i in range(sheet.nrows): # i从0开始
tmp = [] # 定义一个空数组变量
# 逐列读取
for j in range(sheet.ncols):
value = sheet.cell_value(i, j)
tmp.append(value) # add one value
contents.append(tmp) # first row
return contents
- 创建输出调试表格的函数
def printTable(self, table):
# 逐行输出
for i in range(len(table)):
print(table[i]) # 逐个输出最后一列
- 修改OnOpenExcel函数读取和修改表格
def OnOpenExcel(self):
print('I am in OnOpenExcel().')
self.LoopTable = self.readExcelTable("loop.xlsx") # 打开文件:
rows = len(self.LoopTable)
if rows < 1:
return 1
self.printTable(self.LoopTable)
return 0
- 运行效果:
['ms', 'Cir 0', 'Cir 1', 'Cir 2', 'Cir 3', 'Cir 4', 'Cir 5', 'Cir 6', 'Cir 7', 'Cir 8', 'Cir 9', 'Cir 10', 'Cir 11']
['', 'Green', 'Green', 'Green', 'Green', 'Green', 'Green', 'Green', 'Green', 'Green', 'Green', 'Green', 'Green']
[0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
[50.0, 90.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
[100.0, 80.0, 90.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
...
如果学员没有调试出来,可以把SVN代码仓切换到版本8,查看效果。
2 根据表格轮换图片
SVN代码仓切换到版本8。
修改部分变量,添加函数:
- 修改ImageLoop函数:
def ImageLoop(self, angle, percent):
# 图像坐标的0点在左上角
x = self.x + self.R * \
math.sin(angle * math.pi / 180) # 圆的x坐标,向右为正
y = self.y + self.R * \
math.cos(angle * math.pi / 180) # 圆心y坐标,向下为正
self.ImageCircle(self.imgOutput, x, y, self.r, percent) # 往输入的图片上画图形
self.ShowCVImage(self.imgOutput, self.labelOutPut) # 显示到InputLabel上
return 0
- 添加一个Loop按钮来显示图片。
曹函数命名:OnImageLoop,
代码如下:
def OnImageLoop(self):
print('I am in OnImageLoop().')
LastIndex = len(self.LoopTable) - 3
if LastIndex < 0:
return 1
if self.LoopIndex >= LastIndex:
self.LoopIndex = 0
img = self.imgInput.copy() # 复制一个拷贝
self.imgOutput = img # 记录下来
row = self.LoopTable[self.LoopIndex + 2]
cols = len(row)
for i in range(1, cols):
self.ImageLoop(self.angle, row[i])
self.angle += 30
self.angle = self.angle % 360
self.LoopIndex += 1
return 0
通过loop的百分比,来循环绘制图像
效果图:
如果学员没有调试出来,可以把SVN代码仓切换到版本:9,查看效果。
3 使用QTimer控制动画
SVN代码仓切换到版本9。
添加按钮pushButtonAutoLoop,界面文字:Auto Loop
添加2个QLabel,显示动画的id和时间(毫秒)
定义变量:
self.LoopCounter = 0
self.LoopMax = 0
修改函数OnImageLoopAuto,通过self.startTimer(100)启动计时器,100毫秒触发一次,触发后就会运行timerEvent(self, event)函数。
def OnImageLoopAuto(self):
if self.time_id > 0:
return 0 # 防止重复点击启动计时器
self.time_id = self.startTimer(100) # 100ms,0.1s
self.LoopCounter = 0
self.LoopMax= len(self.LoopTable) - 2
return 0
重载函数:timerEvent,在达到一定条件下,停止计时器,
通过语句self.killTimer(self.time_id) 来停止。
所以要提前记录下来计时器的id。
但是这个方法不靠谱。容易出问题。
有可能计时器已经被删除了。
def timerEvent(self, event):
# 定时器经过设定的时间会调用这个函数,循环调用,直到被kill
self.LoopCounter += 1
if self.LoopCounter < 0:
self.LoopCounter = 0
self.OnImageLoop()
self.labelTimeCounter.setText(str(self.LoopCounter))
if(self.LoopCounter >= self.LoopMax):
if self.time_id >0 :
self.killTimer(self.time_id) # 结束定时
self.time_id = -1
else:
text = ''
id = self.LoopCounter + 2
if id < len(self.LoopTable):
row = self.LoopTable[id]
if len(row) > 0:
text = str(row[0])
if text[-2:] == '.0':
text = text[0:-2]
self.labelTime.setText(text)
self.labelTimeCounter.setText(str(self.LoopCounter))
如果学员没有调试出来,可以把SVN代码仓切换到版本11,查看效果。
4 保存动画
把一个序列的图片,保存为avi视频
请等待,没有完成
5 问题处理
QT Toolbar简单示例
QT menu简单示例