简体   繁体   English

让after()方法按时运行Tkinter

[英]Have after() method run on time Tkinter

I'm programming a tool that has to display a timer with 1/100 of second as precision in Tkinter with python. 我正在编程一个工具,该工具必须使用python在Tkinter中显示精度为1/100秒的计时器。 I've tried using the after() method with self.timerLabel.after(0, self.update_timer) 我尝试将after()方法与self.timerLabel.after(0, self.update_timer)

def update_timer (self):
        self.timer += 0.01
        self.timerLabel.configure(text="%.2f" % self.timer)
        self.timerLabel.after(10, self.update_timer)

The problem is that it runs way slower than expected and I need to know if there's a workaround or some way to have the timer run exactly on time. 问题是它的运行速度比预期的慢,我需要知道是否存在解决方法或某种方式使计时器准确地按时运行。 Or maybe some way to use the computer's time to display the correct elapsed time on the screen. 或者,可以使用某种方式使用计算机的时间在屏幕上显示正确的经过时间。 Thank you in advance 先感谢您

The most accurate method is probably to find a start time, then every time you call the update timer function just subtract the start time from the current time. 最准确的方法可能是找到开始时间,然后每次调用更新计时器功能时,只需从当前时间中减去开始时间即可。

I've attached some example code to show you roughly how it would work. 我附加了一些示例代码,向您大致展示了它的工作方式。 It should be fairly simple to adapt that to use after() for Tkinter . 使它适应Tkinter after()应该很简单。

import time

# Start time
startTime = time.time();

def update_timer():

  # Find difference and print
  timeDifference = time.time() - startTime;
  print(timeDifference);

  # Sleep appropriate amount of time before printing
  # next statement.
  time.sleep(0.1);

  # Recursively call update.
  update_timer();

# Start running
update_timer();

Example fiddle: https://repl.it/Hoqh/0 小提琴示例: https : //repl.it/Hoqh/0

The after command makes no guarantees, other than it will not execute before the given time period. after命令不作任何保证,除非它不会在给定时间段之前执行。 Tkinter is not a real time system. Tkinter不是实时系统。

You also have to take into account the time it takes to execute the code. 您还必须考虑执行代码所需的时间。 For example, let's assume that your command starts precisely on time. 例如,假设您的命令正好按时启动。 In that code you have two lines of code: 在该代码中,您有两行代码:

self.timer += 0.01
self.timerLabel.configure(text="%.2f" % self.timer)

That code takes some amount of time to execute. 该代码需要花费一些时间才能执行。 It may be only a few microseconds, but it's definitely more than zero microseconds. 可能只有几微秒,但绝对超过零微秒。

You then call after again: 然后调用after再次:

self.timerLabel.after(10, self.update_timer)

The next time it will run will be at least 10 ms after the current time, which is a few microseconds or milliseconds after it was called. 下次运行将在当前时间之后至少10毫秒,这是调用后的几微秒或毫秒。 So, if the first two commands take 1ms, then the next time you call it will be 11 ms after the first call (10ms for the delay, plus 1ms for the code to execute) 因此,如果前两个命令花费1毫秒,那么下次调用时将是第一次调用之后的11毫秒(延迟为10毫秒,执行代码为1毫秒)

You can minimize the delay factor a little by calling after immediately, rather than waiting for the rest of the code to execute. 你可以通过调用最小化延迟因素一点after立即,而不是等待代码的其余部分执行。 As long as the delay is greater than the time that it takes to execute the other code, you'll notice a slight improvement: 只要延迟大于执行其他代码所花费的时间,您就会注意到有一点改进:

def update_timer (self):
    self.timerLabel.after(10, self.update_timer)
    self.timer += 0.01
    self.timerLabel.configure(text="%.2f" % self.timer)

This still won't be precise, since there are other things that can prevent self.timer from being called exactly 10ms after it was requested. 这仍然是不精确的,因为还有其他一些因素可以阻止self.timer在被请求后的10ms内准确调用。 For example, if the window is resized or moved at 9.99ms, tkinter will have to handle the redraw before it can handle the scheduled task. 例如,如果调整窗口大小或在9.99ms处移动窗口,则tkinter必须先处理重绘,然后才能处理计划的任务。

If you want to account for all of this drift, don't just automatically increment by 10ms each time. 如果要考虑所有这些漂移,不要每次都自动增加10ms。 Instead, calculate the time between each invocation, and add the delta. 而是,计算每次调用之间的时间,并添加增量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM