Seite 1 von 1

TkAnalogClock

Verfasst: Montag 17. Januar 2005, 20:32
von mawe
Hi!

Tadaa! Das Warten hat ein Ende ... ihr habt doch alle darauf gewartet, oder? :wink:
Wie auch immer, das ist das Widget, das mir bei Tkinter am meisten gefehlt hat (stimmt gar nicht) - eine analoge Uhr.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

'''
    Program:         TkAnalogClock
    Description:     A Tkinter Analog Clock widget 
    Version:         0.1
    Copyright:       2005 by Markus Weihs
    Created:         2005-01-17
    Last modified:   2005-01-17
    Licence:         GPL
'''

from Tkinter import *
import thread
import cmath
import time

class TkAnalogClock(Canvas):
	
	_grad = 0.1047
	
	def __init__(self,master,size=100,clockbg='white',timeshift=0,show_second=1,**kw):
		Canvas.__init__(self,master,width=size,height=size,**kw)
		
		self.show_second = show_second
		self.clockbg = clockbg
		self.timeshift = timeshift
		self.size = size
		self.__setup()
	
	def __setup(self):
		size = self.size
		c = size/2
		s = c/10
		if size < 100:
			mthick,hthick = 2,3
		else:
			mthick,hthick = 4,5
		dot_min = 1
		dot_max = dot_min + 4
		ldot_min = dot_max + c/10
		
		self.center = [c,c]
		self.create_oval(1,1,size-1,size-1,fill=self.clockbg)
		self.create_oval(c-hthick,c-hthick,c+hthick,c+hthick,fill='black')
		
		n =  [(c-1,dot_min),(c-1,dot_max),(c+1,dot_max),(c+1,dot_min)]
		nl = [(c-1,ldot_min),(c-1,dot_min),(c+1,dot_min),(c+1,ldot_min)]
		for i in range(60):
			if i%5 == 0:
				self.create_polygon(nl)
				self.__rotate(self._grad*i,nl,None)
			else:
				if size > 99:
					self.create_polygon(n)
					self.__rotate(self._grad*i,n,None)
		
		self.coords = {
			"second": [(c-1,c),(c-1,c-size*0.4),(c+1,c-size*0.4),(c+1,c)],
			"minute": [(c-mthick,c),(c,c-size*0.4),(c+mthick,c)],
			"hour"  : [(c-hthick,c),(c,c-size*0.25),(c+hthick,c)]
		}

		if self.show_second:
			self.create_polygon(self.coords["second"],tags="second")
		self.create_polygon(self.coords["minute"],tags="minute")
		self.create_polygon(self.coords["hour"],tags="hour")

		h,m,s = time.localtime()[3:6]
		h = h+self.timeshift
		
		self.__rotate(self._grad*(h%12*5+m/12),self.coords["hour"],"hour")
		self.__rotate(self._grad*m,self.coords["minute"],"minute")	
		if self.show_second:
			self.__rotate(self._grad*s,self.coords["second"],"second")
		
		thread.start_new_thread(self.__tick, (h,m,s))

	def __rotate(self,direction,coordinates,tag):
		angle = cmath.exp(direction*1j)
		offset = complex(self.center[0], self.center[1])
		newxy = []
		for x,y in coordinates:
			v = angle * (complex(x,y) - offset) + offset
			newxy.append((v.real,v.imag))
		self.delete(tag)
		self.create_polygon(newxy,tags=tag)
		if tag:
			self.coords[tag] = newxy
		self.update()

	def __tick(self,h,m,s):
		while 1:
			s += 1
			if s % 60 == 0: 
				s = 0
				m += 1
				self.__rotate(self._grad,self.coords["minute"],"minute")
				if m % 12 == 0:
					h += 1
					self.__rotate(self._grad,self.coords["hour"],"hour")
			if self.show_second:	
				self.__rotate(self._grad,self.coords["second"],"second")
			time.sleep(1)	

if __name__ == '__main__':
	root = Tk()
	
	f = Frame()
	f.pack(side=LEFT)

	Label(f,text="London").grid(row=0,column=0)
	Label(f,text="Paris").grid(row=0,column=1)	
	Label(f,text="NewYork").grid(row=2,column=0)
	Label(f,text="Peking").grid(row=2,column=1)
	TkAnalogClock(f,size=100,timeshift=-1).grid(row=1,column=0)
	TkAnalogClock(f,size=90,timeshift=-2,show_second=0).grid(row=1,column=1)
	TkAnalogClock(f,size=70,timeshift=1).grid(row=3,column=0)
	TkAnalogClock(f,size=50,timeshift=2,show_second=0).grid(row=3,column=1)
	
	TkAnalogClock(root,size=200,clockbg="red").pack(side=RIGHT)
	
	root.mainloop()
Die Zeitzonen im Beispiel stimmen nicht wirklich (wenn doch, ist das keine Absicht :wink:).

Freue mich wie immer über Kritik.

Gruß, mawe