赞
踩
一个python小作业没想到引出这么多麻烦。要求是实现类似IPHONE手机得秒表计时,精确到小数点后两位(毫秒级),大概就是这种形式00:00.00,由分到毫秒。
看到有得人用wx.Timer设置定时器,但都是以秒为最小单位得,参数设置为毫秒时,如timer.Start(10),10ms时就会发现计时器跑一分钟比正常时间慢了6s左右。
又想到用time.time方法来,但是使用了while循环,页面刷新太快导致wx主界面卡死了,然后就一筹莫展。
最后用了线程,把time.time方法放到线程里执行,只传回参数来更新页面。这样初步是可以了,但是还有几个后续问题。
一个是还是会慢一些,大概会慢6s,但是可以通过修改代码解决,干脆不用tiem.time方法,只用while循环加sleep,每次时间加0.01s,但是sleep(0.009),少睡的0.001用于跑程序,因为1分钟大概误差6s,也就是6000ms,1分钟,程序更新时间的代码运行60000ms/10ms次,也就是6000次,6000次误差6000ms,每次误差1ms,也就是0.001s,所以sleep(0.01-0.001)。这样就弥补了误差,和正常时间无差。代码中有用来测试误差的备注代码,显示01:00.00时,时间戳结果为59.9820001125,这是不一定的,有时为59.99等,还是不错的精度(关于时间最关心的就是精度了,暂时最精确的时间是原子钟,为什么说暂时呢,因为原子钟过几十亿年也会产生1s误差,但是已经是人类能得到的最精确的时间了,机器会存在误差,关于时间精度的极限:没有最准,只有更准,这是我个人对于时间精度的理解)
第二个是使用wx.statictext控件来更新时间的话会导致有闪烁,具体原因不太清楚,可能是控件界面更新太快了,试了下几种解决方法后干脆改成led显示,led数字也是wx自带的,解决了这个问题。
代码中有一些按钮的转换逻辑,以及添加了背景图片,以及利用sqlite3保存了数据,判断了计时上限,判断了保存状态等等等这些细节,可以自己看情况修改。
下面直接上代码,基本都有注释,但是使用线程传递数据这点需要自己好好理解。
下面展示完整代码。
https://blog.csdn.net/weixin_43141119/article/details/105239008 这个是不使用线程的其他做法 欢迎移步
(关于时间上的区别 我的做法显示的是连续的时间 但是会损失了精度 这个做法时间精确 但是显示的却是不连续的时间)
#coding = utf-8 import wx import wx.gizmos as gizmos import time import threading import os import sqlite3 #返回一个唯一的事件类型ID赋值给EVT_RESULT_ID EVT_RESULT_ID = wx.NewId() #自定义一个事件类型,用于线程向主界面传递数据 class ResultEvent(wx.PyEvent): def __init__(self, data): wx.PyEvent.__init__(self) self.SetEventType(EVT_RESULT_ID) self.data = data #自定义事件绑定函数,类似wx自带的wx.EVT_BUTTON def EVT_RESULT(win, func): win.Connect(-1, -1, EVT_RESULT_ID, func) #定义线程类 class WorkerThread(threading.Thread): def __init__(self, notify_window): threading.Thread.__init__(self) self._notify_window = notify_window self.resume_reset = 0#用于区分继续和重启线程 self.__flag = threading.Event()#控制线程暂停或启动 self.start() #启动线程,循环计时 def run(self): t = 0 #测试一分钟误差代码 #starttime = time.time() while True: t += 10 mm = int((t/1000) / 60) ss = int((t/1000) % 60) xx = int((t%1000) / 10) text_time = "{:02d}:{:02d}.{:02d}".format(mm,ss,xx) #if mm == 01 and ss == 00 and xx == 00: #测试一分钟误差代码 #print (time.time() - starttime) #self.__flag.clear() if mm == 59 and ss == 59 and xx == 99: self.__flag.clear() #向MainFrame传递时间 wx.PostEvent(self._notify_window, ResultEvent(text_time)) time.sleep(0.009) #重置秒表 if self.resume_reset == 1: wx.PostEvent(self._notify_window, ResultEvent("00:00.00")) t = 0.0 self
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。