Canvas对象生成之后,有时会希望调整对象的位置。例如前面文章中提到的时钟小程序,我们稍加改造可以另外实现一个指针式时钟:

在这个小程序中增加的功能就是根据具体时间计算每个指针的坐标信息,这部分功能在时钟类Clock中实现。这个Clock类修改自前一篇文章中的DitialClock类:
class Clock:def __init__(self, canvas, width, height):self.canvas = canvasself.width = widthself.height = heightself.digital = True# create font for date.ftDate = Font(family='Times', size=32)self.canvas.create_text(width / 2, height / 4,text='',font=ftDate,tag='date')# create font for time.self.ftTime = Font(family='Times', size=64)self.set_type('Digital')
到14行为止的内容都和DitgitalClock相同,第15行调用set_type方法来选择时钟的类型:
def set_type(self, type):if type=='Digital':self.canvas.create_text(self.width / 2, self.height / 2,text='',font=self.ftTime,tag='time')self.canvas.delete('hour')self.canvas.delete('minute')self.canvas.delete('second')self.canvas.delete('center')else:self.canvas.delete('time')self.canvas.create_line(self.width / 2, self.height / 2,self.width / 2, self.height / 2,width=15,fill='red',arrow=LAST,arrowshape=(self.width / 20, self.width / 10, self.width / 40),tag='hour')self.canvas.create_line(self.width / 2, self.height / 2,self.width / 2, self.height / 2,width=10,fill='green',capstyle=ROUND,tag='minute')self.canvas.create_line(self.width / 2, self.height / 2,self.width / 2, self.height / 2,width=3,fill='blue',capstyle=ROUND,tag='second')center_r = 10self.canvas.create_oval(self.width / 2 - center_r,self.height / 2 - center_r,self.width / 2 + center_r,self.height / 2 + center_r,fill='white',tag='center')self.update()
代码的内容虽长,内容却很简单:构建需要的对象,消除不需要的对象。更新时钟的内容则是根据类型对不同的对象进行更新:
def update(self):now = time.localtime()time_str = time.strftime('%Y.%m.%d %a %p', now)self.canvas.itemconfigure('date', text=time_str)if type=='Digital':time_str = time.strftime('%I:%M:%S', now)self.canvas.itemconfigure('time', text=time_str)else:self.draw_hour(now.tm_hour)self.draw_minute(now.tm_min)self.draw_second(now.tm_sec)
描画指针的部分是指针式时钟特有的部分,其内容是根据小时,分,秒分别计算每个指针的坐标并更新到相应的对象。在Canvas中可以使用coords方法为对象设置新坐标。Tkinter中更新坐标信息之后并不需要另外调用一个画面更新之类的方法,更新结果会直接反映到画面上。
def draw_second(self, second):self.__draw_hand('second', self.width * 0.4, second, 60)def draw_minute(self, minute):self.__draw_hand('minute', self.width * 0.3, minute, 60)def draw_hour(self, hour):self.__draw_hand('hour', self.width * 0.25, hour % 12, 12)def __draw_hand(self, hand, radius, value, system):radians = value / system * 2 * math.pi - math.pi / 2self.canvas.coords(hand,self.width / 2, self.height / 2,self.width / 2 + radius * math.cos(radians),self.height / 2 + radius * math.sin(radians))
接下来是主程序,首先是构建主窗口。和之前的代码稍有不同,代码禁止了主窗口的大小调整功能并为之设置了标题。
# create the main windowroot = Tk()root.resizable(False, False)root.title('Tkinter Clock V1.0')
增加一个OptionMenu控件用于切换数字式时钟和指针式时钟。
clock_type = StringVar()clock_type.set('Digital')enable_menu = OptionMenu(root, clock_type, 'Digital', 'Analog ')enable_menu.grid(row = 0, column = 0, sticky=W)
构建Canvas和时钟对象。
# create canvascanvas = Canvas(root, height= 400, width= 400, relief=SUNKEN)canvas.grid(row=1, column=0)clock = Clock(canvas, 400, 400)
监视变量的变化并进行时钟类型切换:
def var_changed(*args):clock.set_type(clock_type.get())# set variable observer.clock_type.trace_variable('w', var_changed)
构建并启动定时器:
timer = Timer(root, 1000, clock.update)timer.start()
启动主窗口,并在mainloop结束后关闭定时器:
root.mainloop()timer.stop()
完整代码可以从以下地址下载:
https://github.com/xueweiguo/TkinterPrimer/blob/master/Sample/25%20AnalogClock.py
觉得本文有帮助?请分享给更多人。
阅读更多更新文章,请关注微信公众号【面向对象思考】
转载:https://blog.csdn.net/craftsman1970/article/details/102489590