神奇时钟
程序说明
程序的文件名称为Clock.py,程序除了要用到前两个项目已经熟悉的Python语言功能之外,还要使用SimpleGUITk来在画布中绘制文字和图像,并通过SimpleGUITk的计时器定期更新画布中的文字和图像。
通过该项目你可以获得以下能力:
了解Python处理日期时间的技巧
了解simpleguitk绘制文字和图像的功能
理解时间事件的工作原理
增强逻辑思维能力
培养解决问题的能力
编码步骤
我们已经为该小项目提供了一个基本模板,我们建议 “时钟”游戏的开发策略为:
1、确定一组存储游戏状态的全局变量。显而易见,你需要两个全局变量来保存数显要使用的日期字符串(格式为:XXXX年XX月XX日)、时间字符串(格式为: XX时XX分XX秒X)、三个全局变量来保存决定时针、分针、秒针位置的小时(或对应的角度)、分(或对应的角度)、秒(或对应的角度),也许还需要其它一些全局变量标志按钮的状态等。
2、查看datetime模块包中的now()函数,该函数会返回一个datetime对象,其中包含我们关心的所有信息,包括系统时钟所决定的年、月、日、时、分、秒、微秒等。
3、编写get_time()函数,在该函数中调用datetime.now(),然后对日期、时间、角度等全局变量进行计算和处理。
4、编写时钟事件的处理函数tick(),在该函数中根据游戏状态(玩家整秒时刻点击“关闭音乐”是否成功)调用get_time()函数来定期更新重要的全局变量。
5、依次双击打开本项目的images子文件夹中保存的Clock.jpg、Hour.png、Minute.png、Second.png四个图像文件,它们分别表示表门、时针、分针和秒针,注意观察这些图像的尺寸。
6、编写刷新屏幕事件处理函数draw(canvas),利用simpleguitk模块包在画布中先绘制表门,再根据游戏状态绘制数显文字,然后绘制时针、分针和秒针。注意,时针、分针和秒针的旋转角度由相关的全局变量控制。
7、定义按钮“开启数显”的事件处理函数toggle_display_digit(),注意这是一个开关按钮。
8、定义按钮“播放音乐”的事件处理函数toggle_music_play (),注意这是一个开关按钮。
9、创建窗口。
10、注册事件处理器,注意时间事件处理函数tick()每0.1秒调用1次。
11、启动时钟。
12、调用获取日期时间函数。
13、启动窗口。
项目模板
# "时钟"游戏小项目程序模板
import simpleguitk as gui
import math
from datetime import datetime
# 定义全局变量
# 加载图像资源
clock_face = gui.load_image("http://202.201.225.74/video/PythonResoure/ProjectResource/images/project3/ClockFace.jpg")
hour = gui.load_image("http://202.201.225.74/video/PythonResoure/ProjectResource/images/project3//Hour.png")
minute = gui.load_image("http://202.201.225.74/video/PythonResoure/ProjectResource/images/project3/Minute.png")
second = gui.load_image("http://202.201.225.74/video/PythonResoure/ProjectResource/images/project3//Second.png")
# 加载并设置音乐资源
music_box = gui.load_sound("http://202.201.225.74/video/PythonResoure/ProjectResource/sounds/project3/music_box.ogg")
music_box.set_volume(0.5)
def get_time():
"""定义获取日期时间的辅助函数,获取日期时间"""
pass
#
def toggle_display_digit():
"""定义按钮“开启数显”的事件处理函数,切换数显"""
pass
def toggle_music_play():
"""定义按钮“播放音乐”的事件处理函数,切换音乐播放"""
pass
def tick():
"""定义时钟事件的处理函数(每0.1秒被系统调用1次)"""
pass
def draw(canvas):
"""定义绘制屏幕的处理函数"""
pass
# 创建窗口
# 注册事件处理器
# 启动时钟
# 调用获取日期时间函数
# 启动窗口
以下为完整代码
# "时钟"游戏小项目程序模板
import simpleguitk as gui
import math
from datetime import datetime
# 定义全局变量
interval = 100 # 时间事件处理器触发的周期,0.1秒
hour_radian = 0.0 # 时针角度
minute_radian = 0.0 # 分针角度
second_radian = 0.0 # 秒针角度
digit_date = '' # 日期
play_music = False # 是否播放音乐
success = False # 是否整秒点击 “关闭音乐” 成功
frame_width = 600 # 窗口的宽度
frame_height = 600 # 窗口的高度
digit_time = '' # 时间
display_digit = False # 是否数显
tenth_second = 0 # 十分之秒
# 加载图像资源
clock_face = gui.load_image("http://202.201.225.74/video/PythonResoure/ProjectResource/images/project3/ClockFace.jpg") #600*600
hour = gui.load_image("http://202.201.225.74/video/PythonResoure/ProjectResource/images/project3//Hour.png") #16*600
minute = gui.load_image("http://202.201.225.74/video/PythonResoure/ProjectResource/images/project3/Minute.png") #12*600
second = gui.load_image("http://202.201.225.74/video/PythonResoure/ProjectResource/images/project3//Second.png") #30*600
# 加载并设置音乐资源
music_box = gui.load_sound("http://202.201.225.74/video/PythonResoure/ProjectResource/sounds/project3/music_box.ogg")
music_box.set_volume(0.5)
def get_time():
"""定义获取日期时间的辅助函数,获取日期时间"""
global hour_radian, minute_radian, second_radian, digit_date, digit_time, tenth_second
dt = datetime.now()
second_radian = 2.0 * math.pi * dt.second / 60.0
minute_radian = 2.0 * math.pi * (dt.minute + dt.second / 60.0) / 60.0
tenth_second = dt.microsecond // 100000
if dt.hour <= 12:
hour_radian = 2.0 * math.pi * (dt.hour + float(dt.minute) / 60.0) / 12.0
else:
hour_radian = 4.0 * math.pi * (dt.hour + float(dt.minute) / 60.0) / 24.0
month = ''
if dt.month < 10:
month = '0' + str(dt.month)
else:
month = str(dt.month)
day = ''
if dt.day < 10:
day = '0' + str(dt.day)
else:
day = str(dt.day)
digit_date = str(dt.year) + '年' + month + '月' + day + '日'
digit_time = str(dt.hour) + '时' + str(dt.minute) + '分' + str(dt.second) + '秒' + str(dt.microsecond // 100000)
def toggle_display_digit():
"""定义按钮“开启数显”的事件处理函数,切换数显"""
global display_digit
if not display_digit:
display_digit = True
button1.set_text('关闭数显')
else:
button1.set_text('开启数显')
display_digit = False
def toggle_music_play():
"""定义按钮“播放音乐”的事件处理函数,切换音乐播放"""
global success, play_music
success = False
if not play_music:
play_music = True
music_box.rewind()
music_box.play()
button2.set_text("关闭音乐")
elif play_music:
if tenth_second == 0:
success = True
music_box.pause()
button2.set_text("播放音乐")
play_music = False
def tick():
"""定义时钟事件的处理函数(每0.1秒被系统调用1次)"""
global success
if success == True:
if timer.is_running():
timer.stop()
elif success == False:
get_time()
timer.start()
def draw(canvas):
"""定义绘制屏幕的处理函数"""
canvas.draw_image(clock_face, (300,300), (600,600), (300,300), (600,600))
canvas.draw_image(hour, (8, 300), (16, 600), (302, 300), (16, 600),hour_radian)
canvas.draw_image(minute, (6, 300), (12, 600), (302, 300), (12, 600),minute_radian)
canvas.draw_image(second, (15, 300), (30, 600), (302, 300), (30, 600),second_radian)
if display_digit:
canvas.draw_text(digit_date, (220, 190), 20, "black")
canvas.draw_text(digit_time, (220, 440), 20, "black")
# 创建窗口
frame = gui.create_frame("神奇时钟",frame_height, frame_width)
# 注册事件处理器
timer = gui.create_timer(100, tick)
button1 = frame.add_button("开启数显", toggle_display_digit, 80)
button2 = frame.add_button("播放音乐", toggle_music_play, 80)
# 启动时钟
timer.start()
# 调用获取日期时间函数
frame.set_draw_handler(draw)
# 启动窗口
frame.start()