一、python代码实现及turtle库简单介绍
桌面时钟项目描述
1、使用turtle库绘制时钟外形及表针;
2、使用datetime获取系统时间;
3、时钟动态显示
turtle库基本命令
1、turtle.setup()函数:用于启动一个图形窗口,它有四个参数turtle.setup(width, height, startx, starty)分别是:启动窗口的宽度和高度表示窗口启动时,窗口左上角在屏幕中的坐标位置。
2、turtle.pensize()函数:表示小乌龟运动轨迹的宽度。
3、turtle.pencolor()函数:表示小乌龟运动轨迹的颜色。它包含一个输入参数,这里我们把它设为蓝色,blue,其他颜色单词也可以使用。Turtle采用RGB方式来定义颜色,如果希望获得和图片中颜色一致的小蛇,请输入turtle.pencolor(“#3B9909”)
4、turtle.seth(angle)函数:表示小乌龟启动时运动的方向。它包含一个输入参数,是角度值。0表示向东,90度向北,180度向西,270度向南;负值表示相反方向。程序中,我们让小乌龟向-40度启动爬行,即:向东南方向40度。
5、turtle.circle()函数:让小乌龟沿着一个圆形爬行,参数rad描述圆形轨迹半径的位置,这个半径在小乌龟运行的左侧,rad远位置处。如果 rad为负值,则半径在小乌龟运行的右侧, 参数angle表示小乌龟沿着圆形爬行的弧度值。
6、turtle.fd()函数:表示乌龟向前直线爬行移动表示小乌龟向前直线爬行移动,它有一个参数表示爬行的距离
datetime模块函数
1.datetime.date:表示日期的类,返回year-month-day
2.datetime.datetime:表示日期时间的类,返回年月日,时分秒
3.datetime.time:表示时间的类,
4.datetime.timedelta:表示时间间隔,即两个时间点的间隔
5.datetime.tzinfo:时区的相关信息
python代码示例
import turtle # 导入绘图海龟模块
import datetime # 导入日期时间模块
# 移动一段距离
def skip(distance): # 移动方法,不留移动痕迹
turtle.penup() # 抬笔不绘制
turtle.forward(distance) # 移动指定距离
turtle.pendown() # 落笔移动绘制
def draw_clock_dial(): # 绘制表盘的方法
turtle.reset() # 删除图形归位
turtle.hideturtle() # 隐藏箭头
for i in range(60): # 循环执行60次,一圈为360度所以每一秒的角度为6度
skip(160) # 移动160,相当于表盘圆的半径
# 每5秒绘制一个小时刻度
if i % 5 == 0:
turtle.pensize(7) # 刻度大小
# 画时钟
turtle.forward(20) # 小时刻度的长度为20
skip(-20) # 复原小时刻度的位置
else:
turtle.pensize(1) # 将画笔大小设置为1
turtle.dot() # 绘制分钟刻度的小圆点
skip(-160) # 回到中心位置
turtle.right(6) # 向右旋转6度
def get_week(t): # 获取星期的方法
week = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']
return week[t.weekday()] # 返回当天的星期
def create_pointer(length, name): # 创建指针方法
turtle.reset() # 删除图形归位
skip(-length * 0.1) # 抬笔移动指定距离
turtle.begin_poly() # 记录多边形
turtle.forward(length * 1.1) # 绘制指定长度的指针
turtle.end_poly() # 停止记录多边形
# 注册多边形状
turtle.register_shape(name, turtle.get_poly())
def init_pointer(): # 初始化指针
global secHand, minHand, hurHand, printer
turtle.mode("logo") # 重置Turtle指向上
create_pointer(135,"secHand") # 创建秒针图形
create_pointer(110,"minHand") # 创建分针图形
create_pointer(90,"hurHand") # 创建时针图形
secHand = turtle.Turtle() # 创建秒针turtle对象
secHand.shape("secHand") # 创建指定秒针名称的形状
minHand = turtle.Turtle() # 创建分针turtle对象
minHand.shape("minHand") # 创建指定分针名称的形状
hurHand = turtle.Turtle() # 创建时针turtle对象
hurHand.shape("hurHand") # 创建指定时针名称的形状
for hand in secHand, minHand, hurHand: # 循环遍历三个指针
hand.shapesize(1, 1, 5) # 设置形状拉伸大小和轮廓线
hand.speed(0) # 设置速度为最快
printer = turtle.Turtle() # 创建绘制文字的Turtle对象
printer.hideturtle() # 隐藏箭头
printer.penup() # 抬笔
def move_pointer(): # 移动指针的方法
# 不停的获取时间
t = datetime.datetime.today()
second = t.second + t.microsecond * 0.000001 # 计算移动的秒
minute = t.minute + second/60 # 计算移动的分
hour = t.hour + minute/60 # 计算移动的小时
secHand.setheading(6*second) # 设置秒针的角度
minHand.setheading(6*minute) # 设置分针的角度
hurHand.setheading(30*hour) # 设置时针的角度
turtle.tracer(False) # 关闭绘画效果
printer.forward(65) # 向上移动65
# 绘制星期
printer.write(get_week(t), align="center",font=("Courier", 14, "bold"))
printer.back(130) # 倒退130
# 绘制年月日
printer.write(t.strftime('%Y-%m-%d'), align="center",font=("Courier", 14, "bold"))
printer.home() # 归位
turtle.tracer(True) # 开启绘画效果
turtle.ontimer(move_pointer, 10) # 10毫秒后调用move_pointer()方法
if __name__ == '__main__':
turtle.setup(450, 450) # 创建窗体大小
init_pointer() # 调用初始化指针的方法
turtle.tracer(False) # 关闭绘画效果
draw_clock_dial() # 绘制表盘
move_pointer() # 调用移动指针的方法
turtle.mainloop() # 不关闭窗体
运行结果:
二、MFC代码实现
表盘图大家可以自己找一个,添加到位图资源里就行。
添加了一个定时器,实现指针转动更新
时针、分针、秒针的计算公式:
首先换算成12小时制,h = h % 12
时针每小时相当于于相对于y轴顺时针30度。每分钟0.5度(秒可以忽略)
分针每分钟是6度,秒是0.1度
秒针每秒也是6度。
定义分针秒针时针的长度,按照秒针最长,时针次之,时针最短自己定义下。
然后有了指针的夹角,和长度,就可以得到指针末端的坐标,从时钟中心用LineTo方法画线即可。
MFC代码示例
void CdrawdateDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
UpdateData(TRUE);
CTime time = CTime::GetCurrentTime(); //获得系统时间
m_Sec = time.GetSecond();
m_Min = time.GetMinute();
m_Hour = time.GetHour();
CDC* pDC = GetDC();
CRect rect;
GetClientRect(&rect); //获取客户区域
CBitmap bitmap; //定义图片类
bitmap.LoadBitmap(IDB_BITMAP2); //加载位图
CDC memdc; //定义临时画布
memdc.CreateCompatibleDC(pDC); //创建画布
memdc.SelectObject(&bitmap); //关联图片
int x = rect.Width() / 2;
int y = rect.Height() / 2;
//memdc.DrawText(weekDay(time), &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); // 显示星期
CString csCurrTime;
csCurrTime.Format("%04d-%02d-%02d %s", time.GetYear(), time.GetMonth(), time.GetDay(), weekDay(time));
memdc.DrawText(csCurrTime, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); // 显示当前日期
CPen MinutePen(PS_SOLID, 5, RGB(0, 0, 0)); //设置分针画笔
memdc.SelectObject(&MinutePen);
memdc.MoveTo(x, y);
//绘制分针
memdc.LineTo(x + (long)100 * cos(PI / 2 - 2 * PI*m_Min / 60.0), y - (long)100 * sin(PI / 2 - 2 * PI*m_Min / 60.0));
CPen HourPen(PS_SOLID, 8, RGB(0, 0, 0)); //设置时针画笔
memdc.SelectObject(&HourPen);
memdc.MoveTo(x, y);
//绘制时针
memdc.LineTo(x + (long)60 * cos(PI / 2 - 2 * PI*(5 * m_Hour / 60.0 + m_Min / 12.0 / 60.0))
, y - (long)60 * sin(PI / 2 - 2 * PI*(5 * m_Hour / 60.0 + m_Min / 12.0 / 60.0)));
CPen SecondPen(PS_SOLID, 2, RGB(255, 0, 0)); //设置秒针画笔
memdc.SelectObject(&SecondPen);
memdc.MoveTo(x, y);
memdc.LineTo(x + (long)140 * cos(PI / 2 - 2 * PI*m_Sec / 60.0), y - (long)140 * sin(PI / 2 - 2 * PI*m_Sec / 60.0));//绘制秒针
memdc.MoveTo(x, y);
memdc.LineTo(x + (long)10 * cos(PI / 2 - 2 * PI*(m_Sec + 30) / 60.0), y - (long)10 * sin(PI / 2 - 2 * PI*(m_Sec + 30) / 60.0));//绘制秒针
SecondPen.DeleteObject();
MinutePen.DeleteObject();
HourPen.DeleteObject();
pDC->BitBlt(0, 0, rect.right, rect.bottom, &memdc, 0, 0, SRCCOPY); //复制图片
memdc.DeleteDC(); //复制临时画布到预览窗口
bitmap.DeleteObject(); //删除图片
ReleaseDC(pDC);
CDialogEx::OnTimer(nIDEvent);
}
// 输出cstring(判断今天星期几)
CString CdrawdateDlg::weekDay(CTime oTime)
{
CString str;
int nDayOfWeek = oTime.GetDayOfWeek();
switch (nDayOfWeek)
{
case 1:
str = "星期日";
break;
case 2:
str = "星期一";
break;
case 3:
str = "星期二";
break;
case 4:
str = "星期三";
break;
case 5:
str = "星期四";
break;
case 6:
str = "星期五";
break;
case 7:
str = "星期六";
break;
}
return str;
}
代码运行结果: