首页 > 文章列表 > 如何使用Python代码实现模拟动态指针时钟的功能?

如何使用Python代码实现模拟动态指针时钟的功能?

Python
373 2023-04-26

怎么用Python代码实现模拟动态指针时钟

一、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;

}