文章目录

  • 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的百分比,来循环绘制图像

效果图:

python做动画特效 python怎么制作动画_python做动画特效


如果学员没有调试出来,可以把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))

python做动画特效 python怎么制作动画_python_02


如果学员没有调试出来,可以把SVN代码仓切换到版本11,查看效果。


4 保存动画

把一个序列的图片,保存为avi视频
请等待,没有完成

5 问题处理

QT Toolbar简单示例

QT menu简单示例