Мой индикатор выполнения за одну минуту в Tkinter становится все менее и менее точным с каждым циклом

#python #tkinter #progress-bar

#питон #ткинтеръ #индикатор выполнения #python #tkinter

Вопрос:

подробнее: то, что я пытаюсь создать, — это панель прогресса длиной в минуту, и как только минута заканчивается, она перезапускается и зацикливается. код вверху предназначен для автоматического запуска процесса при начале новой минуты. Проблема в том, что панель синхронизируется и запускается сама по себе просто отлично, но через минуту или две она начинает замедляться на пару секунд, самое запутанное в том, что она совсем не последовательна, она замедляется с разной скоростью каждый раз, когда я ее запускаю. Любая помощь была бы очень признательна.

вот мой код:

 import time
from tkinter import *
import datetime as dt
from tkinter.ttk import *

now = dt.datetime.now()
sync_now = 'd:d:d' % (now.hour, now.minute, now.second)
sync_now_object = dt.datetime.strptime(sync_now, '%H:%M:%S').time()
second_of_day = int(now.hour * 60 * 60   now.minute * 60   now.second)
second_of_day = int(second_of_day / 60) * 60   60
hour = int(second_of_day / 60 / 60)
minute = int((second_of_day % (60 * 60)) / 60)
second = int(second_of_day % 60)
target_time = dt.time(hour, minute, second)
target_time_str = str(target_time)
print(target_time)
print(sync_now)

def time_to_num(time_str):
 hh, mm , ss = map(int, time_str.split(':'))
 return ss   60*(mm   60*hh)

difference_target_now=time_to_num(target_time_str)-time_to_num(sync_now)
print(difference_target_now)
after_difference = difference_target_now*1000
print(after_difference)

# creating Tk window
app = Tk()
app.wm_attributes('-topmost', 1)

# setting geometry of tk window
app.geometry("600x100")

# Using title() to display a message in
# the dialogue box of the message in the
# title bar.
app.title("")

progress = Progressbar(app, orient=HORIZONTAL,
                    length=600, mode='determinate')
def my_progress():
   progress['maximum'] = 60
   progress['value'] = 1
   app.update()
   time.sleep(1)

   progress['value'] = 2
   app.update()
   time.sleep(1)

   progress['value'] = 3
   app.update()
   time.sleep(1)

   progress['value'] = 4
   app.update()
   time.sleep(1)

   progress['value'] = 5
   app.update()
   time.sleep(1)

   progress['value'] = 6
   app.update()
   time.sleep(1)

   progress['value'] = 7
   app.update()
   time.sleep(1)

   progress['value'] = 8
   app.update()
   time.sleep(1)

   progress['value'] = 9
   app.update()
   time.sleep(1)

   progress['value'] = 10
   app.update()
   time.sleep(1)

   progress['value'] = 11
   app.update()
   time.sleep(1)

   progress['value'] = 12
   app.update()
   time.sleep(1)

   progress['value'] = 13
   app.update()
   time.sleep(1)

   progress['value'] = 14
   app.update()
   time.sleep(1)

   progress['value'] = 15
   app.update()
   time.sleep(1)

   progress['value'] = 16
   app.update()
   time.sleep(1)

   progress['value'] = 17
   app.update()
   time.sleep(1)

   progress['value'] = 18
   app.update()
   time.sleep(1)

   progress['value'] = 19
   app.update()
   time.sleep(1)

   progress['value'] = 20
   app.update()
   time.sleep(1)

   progress['value'] = 21
   app.update()
   time.sleep(1)

   progress['value'] = 22
   app.update()
   time.sleep(1)

   progress['value'] = 23
   app.update()
   time.sleep(1)

   progress['value'] = 24
   app.update()
   time.sleep(1)

   progress['value'] = 25
   app.update()
   time.sleep(1)

   progress['value'] = 26
   app.update()
   time.sleep(1)

   progress['value'] = 27
   app.update()
   time.sleep(1)

   progress['value'] = 28
   app.update()
   time.sleep(1)

   progress['value'] = 29
   app.update()
   time.sleep(1)

   progress['value'] = 30
   app.update()
   time.sleep(1)

   progress['value'] = 31
   app.update()
   time.sleep(1)

   progress['value'] = 32
   app.update()
   time.sleep(1)

   progress['value'] = 33
   app.update()
   time.sleep(1)

   progress['value'] = 34
   app.update()
   time.sleep(1)

   progress['value'] = 35
   app.update()
   time.sleep(1)

   progress['value'] = 36
   app.update()
   time.sleep(1)

   progress['value'] = 37
   app.update()
   time.sleep(1)

   progress['value'] = 38
   app.update()
   time.sleep(1)

   progress['value'] = 39
   app.update()
   time.sleep(1)

   progress['value'] = 40
   app.update()
   time.sleep(1)

   progress['value'] = 41
   app.update()
   time.sleep(1)

   progress['value'] = 42
   app.update()
   time.sleep(1)

   progress['value'] = 43
   app.update()
   time.sleep(1)

   progress['value'] = 44
   app.update()
   time.sleep(1)

   progress['value'] = 45
   app.update()
   time.sleep(1)

   progress['value'] = 46
   app.update()
   time.sleep(1)

   progress['value'] = 47
   app.update()
   time.sleep(1)

   progress['value'] = 48
   app.update()
   time.sleep(1)

   progress['value'] = 49
   app.update()
   time.sleep(1)

   progress['value'] = 50
   app.update()
   time.sleep(1)

   progress['value'] = 51
   app.update()
   time.sleep(1)

   progress['value'] = 52
   app.update()
   time.sleep(1)

   progress['value'] = 53
   app.update()
   time.sleep(1)

   progress['value'] = 54
   app.update()
   time.sleep(1)

   progress['value'] = 55
   app.update()
   time.sleep(1)

   progress['value'] = 56
   app.update()
   time.sleep(1)

   progress['value'] = 57
   app.update()
   time.sleep(1)

   progress['value'] = 58
   app.update()
   time.sleep(1)

   progress['value'] = 59
   app.update()
   time.sleep(1)

   progress['value'] = 60
   app.update()
   time.sleep(1)

   app.after(0, my_progress)
progress.pack()

app.after(after_difference, my_progress)
app.mainloop()
  

Комментарии:

1. sleep() будет блокировать tkinter.mainloop() , так что лучше используйте after() вместо этого.

Ответ №1:

Две важные вещи:

  • time.sleep(1) спит не менее одной секунды. Это не точный таймер.
  • Обновление индикатора выполнения также требует времени, что еще больше замедляет процесс

В вашем коде есть блоки, подобные этому:

 progress['value'] = 1
app.update()   # this takes time
time.sleep(1)   # more than 1 second
  

Объединение 60 из них определенно займет больше минуты.

Чтобы получить больше точности, используйте разницу во времени между временем начала и текущим временем и соответствующим образом установите индикатор выполнения.

Вот обновленный код. Он проверяет разницу во времени каждые 1/10 секунды и обновляет индикатор выполнения.

 def my_progress():
   progress['maximum'] = 60
   start = dt.datetime.now()
   while True:
       diff = (dt.datetime.now() - start).total_seconds()  # seconds since bar start
       progress['value'] = diff  # can also use int(diff) to jump 1 sec
       app.update()
       time.sleep(0.1)  # 1/10 second
       if (diff > 60):  # end of bar
          start = dt.datetime.now()  # restart progress