Python是一款强大的编程软件,可以轻松实现我们的多种开发需求。今天我们拿Python中自带的tkinter来开发一个时钟显示器。如下图所示:
时间显示器
一、编程要求
用tkinter写一个漂亮、五彩的时间显示器,要求显示时、分、秒,即时变化,同时显示日期,要小巧、精致,逻辑清晰,代码没有冗余,打开就能显示,不需要安装额外的包。
二、算法分析
如果不需要额外的包,就用Python自带的tkinter,这样打包以后形成的exe文件太会小巧、轻便,打开马上就可以用。首先,我们先用函数法来解决这个问题,然后我们再使用类的写法来进一步优化。
1. 采用函数法实现
在编写过程中,我们首先导入tkinter模块和所需的其他模块。
然后,我们定义了两个函数update_time()和update_date(),用于更新时间和日期的标签。update_time()函数使用time.strftime()函数获取当前时间,并使用config()方法将其更新到time_label上。
接着,我们使用after()方法在1000毫秒(1秒)后再次调用update_time()函数,以实现时间的即时变化。类似地,update_date()ref="http://函数使用datetime.date.today">函数使用datetime.date.today().strftime()获取当前日期,并更新到date_label上。
接下来,我们创建了一个tkinter的根窗口,并设置了窗口的标题、大小和背景颜色。然后,我们定义了用于时间和日期的字体,分别为大号的时间字体和小号的日期字体。
随后,我们创建了两个标签time_label和date_label,用于显示时间和日期。我们使用pack()方法将它们放置在窗口中心位置,并使用font参数设置它们的字体和背景颜色。
最后,我们分别调用update_time()和update_date()函数来开始更新时间和日期的显示。然后,通过调用root.mainloop()进入主事件循环,使窗口保持打开状态。
运行该代码,您将会看到一个小巧、精致的窗口,其中包含一个五彩的时间显示器和日期显示器。时间将以时、分、秒的形式显示,并且会实时更新。日期以年-月-日的形式显示,并且在窗口打开时就会显示当前日期。请注意,这里我们没有使用任何额外的包,仅使用了tkinter和标准库中的time和datetime模块。
import tkinter as tk
from tkinter import font
import time
import datetime
def update_time():
current_time = time.strftime('%H:%M:%S')
time_label.config(text=current_time)
time_label.after(1000, update_time)
def update_date():
current_date = datetime.date.today().strftime('%Y-%m-%d')
date_label.config(text=current_date)
root = tk.Tk()
root.title("时间显示器")
root.geometry("300x200")
root.configure(bg='white')
time_font = font.Font(family="Helvetica", size=48, weight="bold")
date_font = font.Font(family="Helvetica", size=16)
time_label = tk.Label(root, text="", font=time_font, bg='white')
time_label.pack(pady=30)
date_label = tk.Label(root, text="", font=date_font, bg='white')
date_label.pack()
update_time()
update_date()
root.mainloop()
2. 采用类的写法来实现
当将代码转换为类的写法时,我们可以将主要的功能和界面元素封装在一个自定义的ClockApp类中。以下是使用类的方式编写的时间和日期显示器的代码示例:
import tkinter as tk
from tkinter import font
import time,datetime
class ClockApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("时间显示器")
self.geometry("300x200")
self.configure(bg='white')
self.time_font = font.Font(family="Helvetica", size=48, weight="bold")
self.date_font = font.Font(family="Helvetica", size=16)
self.time_label = tk.Label(self, text="", font=self.time_font, bg='white')
self.time_label.pack(pady=30)
self.date_label = tk.Label(self, text="", font=self.date_font, bg='white')
self.date_label.pack()
self.update_time()
self.update_date()
def update_time(self):
current_time = time.strftime('%H:%M:%S')
self.time_label.config(text=current_time)
self.time_label.after(1000, self.update_time)
def update_date(self):
current_date = datetime.date.today().strftime('%Y-%m-%d')
self.date_label.config(text=current_date)
if __name__ == "__main__":
app = ClockApp()
app.mainloop()
在这个例子中,我们定义了一个继承自http://tk.Tk的ClockApp类。在__init__方法中,我们初始化了窗口的标题、大小和背景颜色,并创建了时间和日期标签,设置它们的字体和背景颜色。
update_time和update_date方法与之前的示例中的函数是相同的,用于更新时间和日期的显示。不同之处在于,我们使用self.time_label.after和self.date_label.after方法来周期性地调用这两个方法。
在代码的最后,我们创建了一个ClockApp对象并运行应用程序的主事件循环。
通过这种类的写法,我们将相关的功能组织在一起,使代码更加结构化和可扩展。
3. 采用表盘显示
以上时钟,仅是数字的显示,感觉还不够高端,可以改为一个表盘,上面写上珍惜时间的句子,然后最下面再写上时间和日期,效果可能会更好。如下图所示:
为了实现上述的功能,我们要做到以下几步:
创建一个继承自http://tkinter.Tk的ClockApp类,并初始化窗口的标题、大小和背景颜色。
在窗口中创建一个Canvas部件用于绘制表盘,并将其放置在窗口中。
创建一个Label部件用于显示时间,并将其放置在窗口中,设置其字体和背景颜色。
创建一个Label部件用于显示日期,并将其放置在窗口中,设置其字体和背景颜色。
调用draw_clock方法绘制表盘,包括表盘圆形和刻度线。
调用update_clock方法开始更新时钟。
在update_clock方法中,获取当前时间和日期。
使用strftime方法将时间格式化为字符串,并更新时间标签的文本内容。
使用strftime方法将日期格式化为字符串,并更新日期标签的文本内容。
计算时针、分针和秒针的位置和角度,并使用create_line方法在表盘上绘制它们。
如果存在上一次绘制的秒针图像对象,使用canvas.delete方法删除它。绘制新的秒针图像,并将其保存到self.second_hand成员变量中。
为了消除时针和分针的运动轨迹,我们在绘制时针和分针时,我们需要使用canvas.create_line方法创建新的图像对象,并将其保存到相应的成员变量中。
使用after方法设置一个定时器,每隔一秒钟调用update_clock方法更新时钟的显示。
通过这些步骤,我们创建了一个实时更新的时钟应用程序。它显示当前的时间和日期,并在表盘上绘制时针、分针和秒针,使它们根据实际时间进行更新。同时,修复了秒针、时针、分针的轨迹不消失的问题,确保秒针在更新时正常显示和消失。下面是优化后的时钟代码展示:
import tkinter as tk
from math import cos, sin, pi
from datetime import datetime
class ClockApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("表盘时钟")
self.geometry("400x450")
self.configure(bg='light green')
self.motto_label = tk.Label(self, text="时不待我,只争朝夕!",font=('楷体', 16,'bold'), bg='light green')
self.motto_label.pack()
self.canvas = tk.Canvas(self, width=400, height=360, bg='light green', highlightthickness=0)
self.canvas.pack()
self.time_label = tk.Label(self, font=('Helvetica', 16), bg='light green')
self.time_label.pack(pady=10)
self.date_label = tk.Label(self, font=('Helvetica', 12), bg='light green')
self.date_label.pack()
self.hour_hand = None # 保存时针图像对象
self.minute_hand = None # 保存分针图像对象
self.second_hand = None # 保存秒针图像对象
self.draw_clock()
self.update_clock()
def draw_clock(self):
center_x = 200
center_y = 200
radius = 150
# 绘制表盘
self.canvas.create_oval(center_x - radius, center_y - radius, center_x + radius, center_y + radius,
width=2, outline='blue')
# 绘制刻度线和小时标识
for i in range(12):
angle = (i / 12) * 2 * pi
x1 = center_x + cos(angle) * (radius - 10)
y1 = center_y + sin(angle) * (radius - 10)
x2 = center_x + cos(angle) * radius
y2 = center_y + sin(angle) * radius
self.canvas.create_line(x1, y1, x2, y2, width=3)
hour_x = center_x + cos(angle) * (radius - 25)
hour_y = center_y + sin(angle) * (radius - 25)
self.canvas.create_text(hour_x, hour_y, text=str(i+1), font=('Helvetica', 12), fill='black')
def update_clock(self):
current_time = datetime.now().time()
current_date = datetime.now().date()
# 更新时间标签
time_str = current_time.strftime('%H:%M:%S')
self.time_label.config(text=time_str)
# 更新日期标签
date_str = current_date.strftime('%Y-%m-%d')
self.date_label.config(text=date_str)
# 删除上一次的时针和分针图像
if self.hour_hand:
self.canvas.delete(self.hour_hand)
if self.minute_hand:
self.canvas.delete(self.minute_hand)
# 更新时针
hour = current_time.hour
minute = current_time.minute
second = current_time.second
hour_angle = ((hour % 12) + minute / 60 + second / 3600) * (2 * pi / 12) - pi / 2
hour_length = hour_x = 200 + cos(hour_angle) * 60
hour_y = 200 + sin(hour_angle) * 60
self.hour_hand = self.canvas.create_line(200, 200, hour_x, hour_y, width=4, fill='brown')
# 更新分针
minute_angle = ((minute + second / 60) / 60) * (2 * pi) - pi / 2
minute_length = 90
minute_x = 200 + cos(minute_angle) * minute_length
minute_y = 200 + sin(minute_angle) * minute_length
self.minute_hand = self.canvas.create_line(200, 200, minute_x, minute_y, width=3, fill='green')
# 更新秒针
second_angle = (second / 60.0) * (2 * pi) - pi / 2
second_length = 120
second_x = 200 + cos(second_angle) * second_length
second_y = 200 + sin(second_angle) * second_length
if self.second_hand:
self.canvas.delete(self.second_hand)
self.second_hand = self.canvas.create_line(200, 200, second_x, second_y, width=2, fill='red')
self.after(1000, self.update_clock)
if __name__ == "__main__":
app = ClockApp()
app.mainloop()
三、学后反思
- 函数法和类的写法都可以完成任务,但是相比起来类的写法更加科学、富有逻辑性,后期如何再添加功能也很容易实现。推荐用类的写法。
- 函数的命名要与其功能相一致,从名字上要一下子就可以看出函数的功能,如update_time()函数就是更新时间显示。
- 如果定义一下label可以定义成用途+属性,比如时间的标签就可以定义为time_label,这样才更容易识别。
- 如果遇到复杂的编程可以先画一个思维导图,明确用途、实现步骤等,再逐步实现编程。