Python-数目时钟编写
数码时钟文章参考:
https://blog.csdn.net/u010815486/article/details/82940392
本次项目主要借助turtle第三方库绘制,如果安装turtle库有问题可参考我的另一篇文章
https://blog.csdn.net/wangyang_luyao/article/details/108943114
以下涉及到的所有代码都托管到了我的github上:
https://github.com/wangyang520959/A-clock/tree/master
以下涉及到的函数名及意义:
#绘制数码管
def drawLine(psize,line,draw)
#绘制数码数字
def drawNum(psize,line,num,color)
#把数字返回成一个列表
def numReturn(num)
#画笔向特定方向移动一段距离
def penRun(l)
#绘制时间
def drawTime(tm_new)
#绘制日期
def drawData(tm_new)
#绘制主函数
def draw(year_old,month_old,day_old,hour_old,minute_old)
目录
1.效果设计
下图是我这个项目实现的最终效果也是我一开始想达到的视觉效果
我们每做一个项目的时候都要在最开始有一个自己觉得该有的大概的样子,以方便后期对代码的修改
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lZH040Fk-1602321011271)(https://i.loli.net/2020/10/10/COdv4uHQLKcR7W5.png)]
2.获取当前服务器的时间
这里采用的是time类里面的 localtime() 函数,输出结果则看到了当时的时间
now = time.localtime()
print(time.strftime("%Y-%m-%d %H-%M-%S",now))
3.时间字符转换显示
# 转成字符串
# %y 两位数的年份表示(00-99)
# %Y 四位数的年份表示(000-9999)
# %m 月份(01-12)
# %d 月内中的一天(0-31)
# %H 24小时制小时数(0-23)
# %I 12小时制小时数(01-12)
# %M 分钟数(00=59)
# %S 秒(00-59)
# %a 本地简化星期名称
# %A 本地完整星期名称
# %b 本地简化的月份名称
# %B 本地完整的月份名称
# %c 本地相应的日期表示和时间表示
# %j 年内的一天(001-366)
# %p 本地A.M.或P.M.的等价符
# %U 一年中的星期数(00-53)星期天为星期的开始
# %w 星期(0-6),星期天为星期的开始
# %W 一年中的星期数(00-53)星期一为星期的开始
# %x 本地相应的日期表示
# %X 本地相应的时间表示
# %Z 当前时区的名称
# %% %号本身
4.绘制单根数码管
def drawLine(psize,line,draw):
turtle.pensize(psize)#设置画笔大小
turtle.pu()
turtle.fd(line)
if draw:
turtle.pd()
else:
turtle.pu()
turtle.fd(3*line+5)#设置数码管长度
turtle.pu()
turtle.fd(line)
turtle.right(90)
5.绘制数字
根据绘制一根根数码管,最终绘制成一个数码数字
def drawNum(psize,line,num):
# 第一条线
if num in [2, 3, 4, 5, 6, 8, 9]:
drawLine(psize,line,True)
else:
drawLine(psize,line,False)
if num in [0, 1, 3, 4, 5, 6, 7, 8, 9]:
drawLine(psize,line,True)
else:
drawLine(psize,line,False)
if num in [0, 2, 3, 5, 6, 8, 9]:
drawLine(psize,line,True)
else:
drawLine(psize,line,False)
if num in [0, 2, 6, 8]:
drawLine(psize,line,True)
else:
drawLine(psize,line,False)
turtle.left(90)
if num in [0, 4, 5, 6, 8, 9]:
drawLine(psize,line,True)
else:
drawLine(psize,line,False)
if num in [0, 2, 3, 5, 6, 7, 8, 9]:
drawLine(psize,line,True)
else:
drawLine(psize,line,False)
if num in [0, 1, 2, 3, 4, 7, 8, 9]:
drawLine(psize,line,True)
else:
drawLine(psize,line,False)
turtle.pu()
turtle.left(180)
turtle.update()
绘制数码数字的顺序如图
6.绘制时间与日期
我最开始采用的方式是在一个函数中绘制时分秒一个函数绘制日期,这个方式会出现很大的频闪问题,后面再说解决方法,初期代码如下,大家可以试着自己发挥聪明才智改一下
#绘制时间
def drawTime(tm_hour,tm_min,tm_sec):
turtle.goto(-300,0)
hour = numReturn(tm_hour)
min = numReturn(tm_min)
sec = numReturn(tm_sec)
if len(hour) == 1:
drawNum(5,5,0)
penRun(20)
drawNum(5,5,hour[0])
penRun(20)
else:
for i in range(len(hour)):
num_hour = hour[i]
drawNum(5,5,num_hour)
penRun(20)
turtle.fd(40)
penRun(20)
if len(min) == 1:
drawNum(5,5,0)
penRun(20)
drawNum(5,5,min[0])
penRun(20)
else:
for i in range(len(min)):
num_min = min[i]
drawNum(5,5,num_min)
penRun(20)
turtle.fd(40)
penRun(20)
if len(sec) == 1:
drawNum(5,5,0)
penRun(20)
drawNum(5,5,sec[0])
penRun(20)
else:
for i in range(len(sec)):
num_sec = sec[i]
drawNum(5,5,num_sec)
penRun(20)
def drawData(tm_year,tm_mon,tm_mday):
turtle.goto(-265,-80)
year = numReturn(tm_year)
month = numReturn(tm_mon)
day = numReturn(tm_mday)
for i in range(len(year)):
num_year = year[i]
drawNum(3,3,num_year)
penRun(10)
turtle.fd(30)
penRun(10)
if len(month) == 1:
drawNum(3,3,0)
penRun(10)
drawNum(3,3,month[0])
penRun(10)
else:
for i in range(len(month)):
num_month = month[i]
drawNum(3,3,num_month)
penRun(10)
turtle.fd(30)
penRun(10)
if len(day) == 1:
drawNum(3,3,0)
penRun(10)
drawNum(3,3,day[0])
penRun(10)
else:
for i in range(len(day)):
num_day = day[i]
drawNum(3,3,num_day)
penRun(10)
7.利用多线程库定时刷新时间
要如下图一样做到时间根据秒数刷新我们就要借助另外一个第三方库——threading里面的一个叫做Timer的函数,在Python文档里对该函数的解释为:
'''
class threading.Timer(interval, function, args=None, kwargs=None)
创建一个定时器,在经过 interval 秒的间隔事件后,将会用参数 args 和关键字参数 kwargs 调用 function。如果 args 为 None (默认值),则会使用一个空列表。如果 kwargs 为 None (默认值),则会使用一个空字典。
'''
通过在函数中不停地调用绘制图像的主函数从而达到时间的更新
def draw(year_old,month_old,day_old,hour_old,minute_old):
...
...
...
timer = threading.Timer(0.1, draw(year_old,month_old,day_old,hour_old,minute_old)) # 利用多线程库定时刷新
timer.start()
8.解决频闪问题
1. 初版频闪——大幅度闪烁
如图时钟发生了大幅度的闪烁,造成这样结果的原因是绘制时间日期的函数是依次绘制时分秒和年月日,这里的解决方式就是把是所有数字拆分开并进行等值判断,如果数值没发生变化则跳过重新绘制的部分,修改后代码如下:
def draw(year_old,month_old,day_old,hour_old,minute_old):
now = time.localtime()
turtle.hideturtle() # 隐藏画笔
# turtle.speed(10) # 最
# turtle.tracer(0) #追踪速度
turtle.pu()
if now.tm_hour == hour_old and now.tm_min == minute_old:
turtle.goto(60,0)
drawTime(now.tm_sec)
turtle.pu()
elif now.tm_hour == hour_old and now.tm_min != minute_old:
turtle.goto(60,0)
drawTime(now.tm_sec)
turtle.pu()
turtle.goto(-120,0)
drawTime(now.tm_min)
turtle.pu()
elif now.tm_hour != hour_old:
turtle.goto(60,0)
drawTime(now.tm_sec)
turtle.pu()
turtle.goto(-120,0)
drawTime(now.tm_min)
turtle.pu()
turtle.goto(-300,0)
drawTime(now.tm_hour)
turtle.pu()
if now.tm_year == year_old and now.tm_mon == month_old and now.tm_mday ==day_old:
turtle.goto(60,0)
turtle.pu()
elif now.tm_year == year_old and now.tm_mon == month_old:
turtle.goto(55,-80)
drawData(now.tm_mday)
turtle.pu()
elif now.tm_year == year_old and now.tm_mon != month_old:
turtle.goto(-65,-80)
drawData(now.tm_mon)
turtle.pu()
turtle.goto(55,-80)
drawData(now.tm_mday)
turtle.pu()
elif now.tm_year != year_old:
turtle.goto(-265,-80)
drawData(now.tm_year)
turtle.pu()
turtle.goto(-65,-80)
drawData(now.tm_mon)
turtle.pu()
turtle.goto(55,-80)
drawData(now.tm_mday)
turtle.pu()
hour_old = now.tm_hour
minute_old = now.tm_min
year_old = now.tm_year
month_old = now.tm_mon
day_old = now.tm_mday
timer = threading.Timer(0.1, draw(year_old,month_old,day_old,hour_old,minute_old)) # 利用多线程库定时刷新
timer.start()
2.中版频闪——小幅度闪烁
对绘制时间日期的函数进行了大幅度修改后,呈现出了上图的状态,这里的原因是因为我在此利用了底色数字重新绘制再绘制实时秒数而导致刷新时间快于绘制时间所产生的闪烁,所以我在这里的时候直接推翻了之前的构想,改成对单根数码管绘制的修改:把每个数字不需要的那根数码管以底色绘制,从而消除频闪,修改后绘制单个数字的代码如下:
def drawNum(psize,line,num,color):
# 第一条线
if num in [2, 3, 4, 5, 6, 8, 9]:
turtle.pencolor(color)
drawLine(psize,line,True)
else:
turtle.pencolor('#f3f3f3')
drawLine(psize,line,True)
#第二条线
if num in [0, 1, 3, 4, 5, 6, 7, 8, 9]:
turtle.pencolor(color)
drawLine(psize,line,True)
else:
turtle.pencolor('#f3f3f3')
drawLine(psize,line,True)
#第三条线
if num in [0, 2, 3, 5, 6, 8, 9]:
turtle.pencolor(color)
drawLine(psize,line,True)
else:
turtle.pencolor('#f3f3f3')
drawLine(psize,line,True)
#第四条线
if num in [0, 2, 6, 8]:
turtle.pencolor(color)
drawLine(psize,line,True)
else:
turtle.pencolor('#f3f3f3')
drawLine(psize,line,True)
turtle.left(90)
#第五条线
if num in [0, 4, 5, 6, 8, 9]:
turtle.pencolor(color)
drawLine(psize,line,True)
else:
turtle.pencolor('#f3f3f3')
drawLine(psize,line,True)
#第六条线
if num in [0, 2, 3, 5, 6, 7, 8, 9]:
turtle.pencolor(color)
drawLine(psize,line,True)
else:
turtle.pencolor('#f3f3f3')
drawLine(psize,line,True)
#第七条线
if num in [0, 1, 2, 3, 4, 7, 8, 9]:
turtle.pencolor(color)
drawLine(psize,line,True)
else:
turtle.pencolor('#f3f3f3')
drawLine(psize,line,True)
turtle.pu()
turtle.left(180)
turtle.update()
3.最终版时钟
最终效果如下,因为利用turtle库的画笔而画笔只有一根,导致我在此处没有做到某根数码管亮起的同时另一根数码管熄灭,如果读到这篇文章的你有兴趣的话可以试一下。
4, 7, 8, 9]:
turtle.pencolor(color)
drawLine(psize,line,True)
else:
turtle.pencolor(’#f3f3f3’)
drawLine(psize,line,True)
turtle.pu()
turtle.left(180)
turtle.update()