在此示例中,如何同时启动所有4个秒表?
此示例代码已超过12年,但它是我通过Google找到的最好的秒表示例。您可以看到我正在使用该类的4个实例。我需要能够在同一时间启动所有实例。修补程序按钮不允许调用多个功能。即使它确实如此,它也会在下一个功能之前完成,所以在技术上它们不会都在同一时间开始。
我需要在不同的时间停止每个秒表,但只需调用班级中的每个Stop函数即可。但我无法弄清楚如何同时启动它们。
from Tkinter import *
import time
class StopWatch(Frame):
""" Implements a stop watch frame widget. """
def __init__(self, parent=None, **kw):
Frame.__init__(self, parent, kw)
self._start = 0.0
self._elapsedtime = 0.0
self._running = 0
self.timestr = StringVar()
self.makeWidgets()
def makeWidgets(self):
""" Make the time labels. """
l = Label(self, textvariable=self.timestr)
l.pack(fill=X, expand=NO, pady=2, padx=2)
self._setTime(self._elapsedtime)
def _update(self):
""" Update the label with elapsed time. """
self._elapsedtime = time.time() - self._start
self._setTime(self._elapsedtime)
self._timer = self.after(50, self._update)
def _setTime(self, elap):
""" Set the time string to Minutes:Seconds:Hundreths """
minutes = int(elap/60)
seconds = int(elap - minutes*60.0)
hseconds = int((elap - minutes*60.0 - seconds)*100)
self.timestr.set('%02d:%02d:%02d' % (minutes, seconds, hseconds))
def Start(self):
global sw2
""" Start the stopwatch, ignore if running. """
if not self._running:
self._start = time.time() - self._elapsedtime
self._update()
self._running = 1
def Stop(self):
""" Stop the stopwatch, ignore if stopped. """
if self._running:
self.after_cancel(self._timer)
self._elapsedtime = time.time() - self._start
self._setTime(self._elapsedtime)
self._running = 0
def Reset(self):
""" Reset the stopwatch. """
self._start = time.time()
self._elapsedtime = 0.0
self._setTime(self._elapsedtime)
def main():
root = Tk()
sw1 = StopWatch(root)
sw1.pack(side=TOP)
sw2 = StopWatch(root)
sw2.pack(side=TOP)
sw3 = StopWatch(root)
sw3.pack(side=TOP)
sw4 = StopWatch(root)
sw4.pack(side=TOP)
Button(root, text='Start', command=sw1.Start).pack(side=LEFT)
Button(root, text='Stop', command=sw1.Stop).pack(side=LEFT)
Button(root, text='Reset', command=sw1.Reset).pack(side=LEFT)
Button(root, text='Quit', command=root.quit).pack(side=LEFT)
root.mainloop()
if __name__ == '__main__':
main()
答案 0 :(得分:1)
以下程序可能接近你想要的。请注意,由于启动和停止秒表需要一些时间,因此您可能会发现它们显示的时间差异很小。
#! /usr/bin/env python3
import tkinter
import time
class StopWatch(tkinter.Frame):
@classmethod
def main(cls):
tkinter.NoDefaultRoot()
root = tkinter.Tk()
root.title('Stop Watch')
root.resizable(True, False)
root.grid_columnconfigure(0, weight=1)
padding = dict(padx=5, pady=5)
widget = StopWatch(root, **padding)
widget.grid(sticky=tkinter.NSEW, **padding)
root.mainloop()
def __init__(self, master=None, cnf={}, **kw):
padding = dict(padx=kw.pop('padx', 5), pady=kw.pop('pady', 5))
super().__init__(master, cnf, **kw)
self.grid_columnconfigure(1, weight=1)
self.grid_rowconfigure(1, weight=1)
self.__total = 0
self.__label = tkinter.Label(self, text='Total Time:')
self.__time = tkinter.StringVar(self, '0.000000')
self.__display = tkinter.Label(self, textvariable=self.__time)
self.__button = tkinter.Button(self, text='Start', command=self.click)
self.__label.grid(row=0, column=0, sticky=tkinter.E, **padding)
self.__display.grid(row=0, column=1, sticky=tkinter.EW, **padding)
self.__button.grid(row=1, column=0, columnspan=2,
sticky=tkinter.NSEW, **padding)
def click(self):
if self.__button['text'] == 'Start':
self.__button['text'] = 'Stop'
self.__start = time.clock()
self.__counter = self.after_idle(self.__update)
else:
self.__button['text'] = 'Start'
self.after_cancel(self.__counter)
def __update(self):
now = time.clock()
diff = now - self.__start
self.__start = now
self.__total += diff
self.__time.set('{:.6f}'.format(self.__total))
self.__counter = self.after_idle(self.__update)
class ManyStopWatch(tkinter.Tk):
def __init__(self, count):
super().__init__()
self.title('Stopwatches')
padding = dict(padx=5, pady=5)
tkinter.Button(self, text='Toggle All', command=self.click).grid(
sticky=tkinter.NSEW, **padding)
for _ in range(count):
StopWatch(self, **padding).grid(sticky=tkinter.NSEW, **padding)
def click(self):
for child in self.children.values():
if isinstance(child, StopWatch):
child.click()
if __name__ == '__main__':
ManyStopWatch(4).mainloop()
答案 1 :(得分:1)
" Tinker [sic]按钮不允许调用多个功能。"
不,但它可以调用一个可以调用多个函数的函数。
def start():
for sw in (sw1, sw2, sw3, sw4):
sw.Start()
...
Button(root, text='Start', command=start).pack(side=LEFT)
你是正确的,不可能在同一时间启动它们。虽然,它们都将在一毫秒或两个之内,所以对于大多数情况来说它已经足够好了。由于您只将时间显示为整秒的粒度,因此计时器应始终显示相同的时间。
如果您确实需要同步它们,则需要它们共享相同的确切开始时间。您可以通过允许秒表给出开始时间来做到这一点。然后,您可以计算一次开始时间并将相同的值传递给所有四个手表:
class Stopwatch(Frame):
...
def Start(self, starttime=None):
...
if not self._running:
if starttime is None:
self._start = time.time() - self._elapsedtime
else:
self._start = starttime - self.elapsedtime
...
...
t = time.time()
sw1.Start(t)
sw2.Start(t)
sw3.Start(t)
sw4.Start(t)
您还可以拥有一个所有秒表共享的计时器对象。然后,他们不是那么多的秒表,因为他们是"分裂计时器" - 他们无法控制手表的启动,他们只能记录停止的时间间隔。
答案 2 :(得分:1)
这是我最终做的,基于Bryan的想法,有一个计数器的实例,然后分时间。这有效,但我还没有找到一种方法只使用Getpit函数来抓取每次。也许传递a,b,c,d然后一个如果得到时间?现在我用按钮做这个,但一旦实现它将通过我正在编写的主程序中发生的事件抓住它们。如果有人对此有任何改进,请告诉我。感谢大家的帮助。
from Tkinter import *
import time
import tkMessageBox
class StopWatch(Frame):
""" Implements a stop watch frame widget. """
def __init__(self, parent=None, **kw):
Frame.__init__(self, parent, kw)
self._start = 0.0
self._elapsedtime = 0.0
self._running = 0
self.timestr = StringVar()
self.lapastr = StringVar()
self.lapbstr = StringVar()
self.lapcstr = StringVar()
self.lapdstr = StringVar()
self.makeWidgets()
def makeWidgets(self):
""" Make the time labels. """
la = Label(self, textvariable=self.timestr)
la.pack(fill=X, expand=NO, pady=2, padx=2)
#self._setTime(self._elapsedtime)
lb = Label(self, textvariable=self.timestr)
lb.pack(fill=X, expand=NO, pady=2, padx=2)
#self._setTime(self._elapsedtime)
lc = Label(self, textvariable=self.timestr)
lc.pack(fill=X, expand=NO, pady=2, padx=2)
#self._setTime(self._elapsedtime)
ld = Label(self, textvariable=self.timestr)
ld.pack(fill=X, expand=NO, pady=2, padx=2)
lsplita = Label(self, textvariable=self.lapastr)
lsplita.pack(fill=X, expand=NO, pady=2, padx=2)
lsplitb =Label(self, textvariable=self.lapbstr)
lsplitb.pack(fill=X, expand=NO, pady=2, padx=2)
lsplitc = Label(self, textvariable=self.lapcstr)
lsplitc.pack(fill=X, expand=NO, pady=2, padx=2)
lsplitd = Label(self, textvariable=self.lapdstr)
lsplitd.pack(fill=X, expand=NO, pady=2, padx=2)
self._setTime(self._elapsedtime)
def _update(self):
""" Update the label with elapsed time. """
self._elapsedtime = time.time() - self._start
self._setTime(self._elapsedtime)
self._timer = self.after(50, self._update)
def _setTime(self, elap):
""" Set the time string to Minutes:Seconds:Hundreths """
minutes = int(elap/60)
seconds = int(elap - minutes*60.0)
hseconds = int((elap - minutes*60.0 - seconds)*100)
self.timestr.set('%02d:%02d:%02d' % (minutes, seconds, hseconds))
def Start(self):
""" Start the stopwatch, ignore if running. """
if not self._running:
self._start = time.time() - self._elapsedtime
self._update()
self._running = 1
def Stop(self):
""" Stop the stopwatch, ignore if stopped. """
if self._running:
self.after_cancel(self._timer)
self._elapsedtime = time.time() - self._start
self._setTime(self._elapsedtime)
self._running = 0
def Getsplita(self):
""" Stop the stopwatch, ignore if stopped. """
if self._running:
self._lapstr = time.time() - self._start
self._setTime(self._elapsedtime)
self.lapastr.set(self._lapstr)
def Getsplitb(self):
""" Stop the stopwatch, ignore if stopped. """
if self._running:
self._lapstr = time.time() - self._start
self._setTime(self._elapsedtime)
self.lapbstr.set(self._lapstr)
def Getsplitc(self):
""" Stop the stopwatch, ignore if stopped. """
if self._running:
self._lapstr = time.time() - self._start
self._setTime(self._elapsedtime)
self.lapcstr.set(self._lapstr)
def Getsplitd(self):
""" Stop the stopwatch, ignore if stopped. """
if self._running:
self._lapstr = time.time() - self._start
self._setTime(self._elapsedtime)
self.lapdstr.set(self._lapstr)
def Reset(self):
""" Reset the stopwatch. """
self._start = time.time()
self._elapsedtime = 0.0
self._setTime(self._elapsedtime)
def main():
root = Tk()
sw1 = StopWatch(root)
sw1.pack(side=TOP)
Button(root, text='Start', command=sw1.Start).pack(side=LEFT)
Button(root, text='Stop', command=sw1.Stop).pack(side=LEFT)
Button(root, text='Reset', command=sw1.Reset).pack(side=LEFT)
Button(root, text='Quit', command=root.quit).pack(side=LEFT)
Button(root, text='Get Split A', command=sw1.Getsplita).pack(side=LEFT)
Button(root, text='Get Split B', command=sw1.Getsplitb).pack(side=LEFT)
Button(root, text='Get Split C', command=sw1.Getsplitc).pack(side=LEFT)
Button(root, text='Get Split D', command=sw1.Getsplitd).pack(side=LEFT)
root.mainloop()
if __name__ == '__main__':
main()