之后的Python tkinter
我使用之后的Python tkinter,python,tkinter,raspberry-pi2,Python,Tkinter,Raspberry Pi2,我使用tinter.after()每隔200ms刷新树莓pi上的模拟时钟显示。开始时还可以,但每次刷新之间的时间逐渐达到2-3秒。是否有任何解决方案将刷新间隔保持在200ms #!/usr/bin/env python # coding: UTF-8 # license: GPL # ## @package _08c_clock # # A very simple analog clock. # # The program transforms worldcoordinates into s
tinter.after()
每隔200ms刷新树莓pi上的模拟时钟显示。开始时还可以,但每次刷新之间的时间逐渐达到2-3秒。是否有任何解决方案将刷新间隔保持在200ms
#!/usr/bin/env python
# coding: UTF-8
# license: GPL
#
## @package _08c_clock
#
# A very simple analog clock.
#
# The program transforms worldcoordinates into screencoordinates
# and vice versa according to an algorithm found in:
# "Programming principles in computer graphics" by Leendert Ammeraal.
#
# Based on the code of Anton Vredegoor (anton.vredegoor@gmail.com)
#
# @author Paulo Roma
# @since 01/05/2014
# @see https://code.activestate.com/recipes/578875-analog-clock
# @see http://orion.lcg.ufrj.br/python/figuras/fluminense.png
import sys, types, os
from time import localtime
from datetime import timedelta,datetime
from math import sin, cos, pi
from threading import Thread
try:
from tkinter import * # python 3
except ImportError:
try:
from mtTkinter import * # for thread safe
except ImportError:
from Tkinter import * # python 2
hasPIL = True
# we need PIL for resizing the background image
# in Fedora do: yum install python-pillow-tk
# or yum install python3-pillow-tk
try:
from PIL import Image, ImageTk
except ImportError:
hasPIL = False
## Class for handling the mapping from window coordinates
# to viewport coordinates.
#
class mapper:
## Constructor.
#
# @param world window rectangle.
# @param viewport screen rectangle.
#
def __init__(self, world, viewport):
self.world = world
self.viewport = viewport
x_min, y_min, x_max, y_max = self.world
X_min, Y_min, X_max, Y_max = self.viewport
f_x = float(X_max-X_min) / float(x_max-x_min)
f_y = float(Y_max-Y_min) / float(y_max-y_min)
self.f = min(f_x,f_y)
x_c = 0.5 * (x_min + x_max)
y_c = 0.5 * (y_min + y_max)
X_c = 0.5 * (X_min + X_max)
Y_c = 0.5 * (Y_min + Y_max)
self.c_1 = X_c - self.f * x_c
self.c_2 = Y_c - self.f * y_c
## Maps a single point from world coordinates to viewport (screen) coordinates.
#
# @param x, y given point.
# @return a new point in screen coordinates.
#
def __windowToViewport(self, x, y):
X = self.f * x + self.c_1
Y = self.f * -y + self.c_2 # Y axis is upside down
return X , Y
## Maps two points from world coordinates to viewport (screen) coordinates.
#
# @param x1, y1 first point.
# @param x2, y2 second point.
# @return two new points in screen coordinates.
#
def windowToViewport(self,x1,y1,x2,y2):
return self.__windowToViewport(x1,y1),self.__windowToViewport(x2,y2)
## Class for creating a new thread.
#
class makeThread (Thread):
"""Creates a thread."""
## Constructor.
# @param func function to run on this thread.
#
def __init__ (self,func):
Thread.__init__(self)
self.__action = func
self.debug = False
## Destructor.
#
def __del__ (self):
if ( self.debug ): print ("Thread end")
## Starts this thread.
#
def run (self):
if ( self.debug ): print ("Thread begin")
self.__action()
## Class for drawing a simple analog clock.
# The backgroung image may be changed by pressing key 'i'.
# The image path is hardcoded. It should be available in directory 'images'.
#
class clock:
## Constructor.
#
# @param deltahours time zone.
# @param sImage whether to use a background image.
# @param w canvas width.
# @param h canvas height.
# @param useThread whether to use a separate thread for running the clock.
#
def __init__(self,root,deltahours = 0,sImage = True,w = 400,h = 400,useThread = False):
self.world = [-1,-1,1,1]
self.imgPath = './images/fluminense.png' # image path
if hasPIL and os.path.exists (self.imgPath):
self.showImage = sImage
else:
self.showImage = False
self.setColors()
self.circlesize = 0.09
self._ALL = 'handles'
self.root = root
width, height = w, h
self.pad = width/16
if self.showImage:
self.fluImg = Image.open(self.imgPath)
self.root.bind("<Escape>", lambda _ : root.destroy())
self.delta = timedelta(hours = deltahours)
self.canvas = Canvas(root, width = width, height = height, background = self.bgcolor)
viewport = (self.pad,self.pad,width-self.pad,height-self.pad)
self.T = mapper(self.world,viewport)
self.root.title('Clock')
self.canvas.bind("<Configure>",self.resize)
self.root.bind("<KeyPress-i>", self.toggleImage)
self.canvas.pack(fill=BOTH, expand=YES)
if useThread:
st=makeThread(self.poll)
st.debug = True
st.start()
else:
self.poll()
## Called when the window changes, by means of a user input.
#
def resize(self,event):
sc = self.canvas
sc.delete(ALL) # erase the whole canvas
width = sc.winfo_width()
height = sc.winfo_height()
imgSize = min(width, height)
self.pad = imgSize/16
viewport = (self.pad,self.pad,width-self.pad,height-self.pad)
self.T = mapper(self.world,viewport)
if self.showImage:
flu = self.fluImg.resize((int(0.8*0.8*imgSize), int(0.8*imgSize)), Image.ANTIALIAS)
self.flu = ImageTk.PhotoImage(flu)
sc.create_image(width/2,height/2,image=self.flu)
else:
self.canvas.create_rectangle([[0,0],[width,height]], fill = self.bgcolor)
self.redraw() # redraw the clock
## Sets the clock colors.
#
def setColors(self):
if self.showImage:
self.bgcolor = 'antique white'
self.timecolor = 'dark orange'
self.circlecolor = 'dark green'
else:
self.bgcolor = '#000000'
self.timecolor = '#ffffff'
self.circlecolor = '#808080'
## Toggles the displaying of a background image.
#
def toggleImage(self,event):
if hasPIL and os.path.exists (self.imgPath):
self.showImage = not self.showImage
self.setColors()
self.resize(event)
## Redraws the whole clock.
#
def redraw(self):
start = pi/2 # 12h is at pi/2
step = pi/6
for i in range(12): # draw the minute ticks as circles
angle = start-i*step
x, y = cos(angle),sin(angle)
self.paintcircle(x,y)
self.painthms() # draw the handles
if not self.showImage:
self.paintcircle(0,0) # draw a circle at the centre of the clock
## Draws the handles.
#
def painthms(self):
self.canvas.delete(self._ALL) # delete the handles
T = datetime.timetuple(datetime.utcnow()-self.delta)
x,x,x,h,m,s,x,x,x = T
self.root.title('%02i:%02i:%02i' %(h,m,s))
angle = pi/2 - pi/6 * (h + m/60.0)
x, y = cos(angle)*0.70,sin(angle)*0.70
scl = self.canvas.create_line
# draw the hour handle
scl(self.T.windowToViewport(0,0,x,y), fill = self.timecolor, tag=self._ALL, width = self.pad/3)
angle = pi/2 - pi/30 * (m + s/60.0)
x, y = cos(angle)*0.90,sin(angle)*0.90
# draw the minute handle
scl(self.T.windowToViewport(0,0,x,y), fill = self.timecolor, tag=self._ALL, width = self.pad/5)
angle = pi/2 - pi/30 * s
x, y = cos(angle)*0.95,sin(angle)*0.95
# draw the second handle
scl(self.T.windowToViewport(0,0,x,y), fill = self.timecolor, tag=self._ALL, arrow = 'last')
## Draws a circle at a given point.
#
# @param x,y given point.
#
def paintcircle(self,x,y):
ss = self.circlesize / 2.0
sco = self.canvas.create_oval
sco(self.T.windowToViewport(-ss+x,-ss+y,ss+x,ss+y), fill = self.circlecolor)
## Animates the clock, by redrawing everything after a certain time interval.
#
def poll(self):
self.redraw()
self.root.after(200,self.poll)
## Main program for testing.
#
# @param argv time zone, image background flag,
# clock width, clock height, create thread flag.
#
def main(argv=None):
if argv is None:
argv = sys.argv
if len(argv) > 2:
try:
deltahours = int(argv[1])
sImage = (argv[2] == 'True')
w = int(argv[3])
h = int(argv[4])
t = (argv[5] == 'True')
except ValueError:
print ("A timezone is expected.")
return 1
else:
deltahours = 3
sImage = True
w = h = 400
t = False
root = Tk()
root.geometry ('+0+0')
# deltahours: how far are you from utc?
# Sometimes the clock may be run from another timezone ...
clock(root,deltahours,sImage,w,h,t)
root.mainloop()
if __name__=='__main__':
sys.exit(main())
#/usr/bin/env python
#编码:UTF-8
#许可证:GPL
#
##@package\u 08c\u时钟
#
#一个非常简单的模拟时钟。
#
#程序将世界坐标转换为屏幕坐标
#根据下列算法,反之亦然:
#Leendert Ammeraal的“计算机图形学中的编程原理”。
#
#基于Anton Vredegoor(Anton。vredegoor@gmail.com)
#
#@作者保罗·罗马
#@自2014年5月1日起
#@见https://code.activestate.com/recipes/578875-analog-clock
#@见http://orion.lcg.ufrj.br/python/figuras/fluminense.png
导入系统、类型、操作系统
从时间导入本地时间
从datetime导入timedelta,datetime
从数学输入sin,cos,pi
从线程导入线程
尝试:
从tkinter导入*#python 3
除恐怖外:
尝试:
来自mtTkinter导入*#用于线程安全
除恐怖外:
从Tkinter导入*#python 2
hasPIL=True
#我们需要PIL来调整背景图像的大小
#在Fedora中执行:yum安装python-tk
#或yum安装python3
尝试:
从PIL导入图像,ImageTk
除恐怖外:
hasPIL=False
##用于处理来自窗口坐标的映射的类
#创建视口坐标。
#
类映射器:
##构造器。
#
#@param世界窗口矩形。
#@param视口屏幕矩形。
#
定义初始(自我、世界、视口):
self.world=世界
self.viewport=视口
x_min,y_min,x_max,y_max=self.world
X_min,Y_min,X_max,Y_max=self.viewport
f_x=浮动(x_最大-x_最小)/浮动(x_最大-x_最小)
f_y=浮动(y_max-y_min)/浮动(y_max-y_min)
self.f=min(f_x,f_y)
x_c=0.5*(x_最小值+x_最大值)
y_c=0.5*(y_最小值+y_最大值)
X_c=0.5*(X_最小值+X_最大值)
Y_c=0.5*(Y_最小值+Y_最大值)
self.c_1=X_c-self.f*X_c
self.c_2=Y_c-self.f*Y_c
##将单个点从世界坐标映射到视口(屏幕)坐标。
#
#@param x,y给定点。
#@返回屏幕坐标中的新点。
#
定义窗口到视口(自、x、y):
X=自f*X+self.c_1
Y=self.f*-Y+self.c#u 2#Y轴颠倒
返回X,Y
##将两个点从世界坐标映射到视口(屏幕)坐标。
#
#@参数x1,y1第一点。
#@param x2,y2第二点。
#@返回屏幕坐标中的两个新点。
#
def windowToViewport(自身、x1、y1、x2、y2):
返回self.\u windowToViewport(x1,y1),self.\u windowToViewport(x2,y2)
##用于创建新线程的类。
#
类makeThread(线程):
“”“创建线程。”“”
##构造器。
#@param func函数在该线程上运行。
#
定义初始化(self,func):
线程。\uuuu初始化\uuuuu(自)
自身动作=功能
self.debug=False
##析构函数。
#
定义(自我):
if(self.debug):打印(“线程结束”)
##启动此线程。
#
def运行(自):
if(self.debug):打印(“线程开始”)
自我行动()
##用于绘制简单模拟时钟的类。
#按“i”键可更改背景图像。
#图像路径是硬编码的。它应该在“images”目录中可用。
#
班级时钟:
##构造器。
#
#@param deltahours时区。
#@param sImage是否使用背景图像。
#@param w画布宽度。
#@param h画布高度。
#@param useThread是否使用单独的线程运行时钟。
#
def u uu init u uuu(self、root、deltahours=0、sImage=True、w=400、h=400、useThread=False):
self.world=[-1,-1,1,1]
self.imgPath='./images/fluminense.png'#图像路径
如果hasPIL和os.path.exists(self.imgPath):
self.showImage=sImage
其他:
self.showImage=False
self.setColors()
self.circlesize=0.09
self.\u ALL='handles'
self.root=根
宽度,高度=w,h
self.pad=宽度/16
如果self.showImage:
self.fluImg=Image.open(self.imgPath)
self.root.bind(“,lambda::root.destroy())
self.delta=timedelta(小时=deltahours)
self.canvas=canvas(根,宽度=宽度,高度=高度,背景=self.bgcolor)
视口=(self.pad、self.pad、宽度self.pad、高度self.pad)
self.T=mapper(self.world,viewport)
self.root.title('Clock')
self.canvas.bind(“,self.resize)
self.root.bind(“,self.toggleImage)
self.canvas.pack(fill=BOTH,expand=YES)
如果使用线程:
st=makeThread(self.poll)
st.debug=True
圣斯特朗
其他:
self.poll()
##在窗口更改时通过用户输入调用。
#
def调整大小(自身、事件):
sc=自我画布
sc.delete(ALL)#擦除整个画布
宽度=sc.winfo_宽度()
高度=sc.winfo_高度()
imgSize=最小值(宽度、高度)
self.pad=imgSize/16
视口=(self.pad、self.pad、宽度self.pad、高度self.pad)
self.T=mapper(self.world,viewport)
如果self.showImage:
flu=self.fluImg.resize((int(0.8*0.8*imgSize),int(0.8*imgSize)),Image.ANTIALIAS)
self.flu=ImageTk.PhotoImage(flu)
sc.create_图像(宽度/2,高度/2,图像=self.flu)
其他:
canvas.create_矩形([[0,0],[width,height]],fill=self.bgcolor)
self.redraw()#重新绘制时钟
##设置时钟颜色。
#
def设置颜色(
def callback(self):
<do some work>
self.after(200, self.callback)
def callback(self):
self.after(200, self.callback)
<do some work>