После этого ткинтер переживает перемотку часов - PullRequest
9 голосов
/ 18 июня 2010

Я заметил, что в моей версии Tkinter вызов after () не выдерживает перемотку системных часов.

Если after (x, func) был вызван и системные часы были перезаписаны, func будет вызван только после того, как часы вернутся к своему времени до перемотки + x миллисекунд.

Я предполагаю, что это потому, что Tkinter использует системные часы вместо "time.clock" (количество времени, в течение которого программа работает).

Я тестировал его только на Windows, и, может быть, потому, что у меня старая версия Tkinter. Я хочу, чтобы мое приложение работало на компьютерах, которые синхронизируют свои часы из сети ...

У кого-нибудь есть простое решение?

Ответы [ 2 ]

5 голосов
/ 27 апреля 2019

К сожалению, ни Tkinter, ни Tcl-интерпретатор не имеют прямого решения вашей проблемы.Метод after(ms, func) основан на команде Tcl с тем же именем, которая создает внутренний таймер на основе текущего системного времени плюс количество миллисекунд, переданных в качестве параметра.

Если вам интересно, вы можетепроверить это непосредственно из исходного кода Tcl / Tk :

Tcl_GetTime(&wakeup);
wakeup.sec += (long)(ms / 1000);
wakeup.usec += ((long)(ms % 1000)) * 1000;
if (wakeup.usec > 1000000) {
    wakeup.sec++;
    wakeup.usec -= 1000000;
}
afterPtr->token = TclCreateAbsoluteTimerHandler(&wakeup,
    AfterProc, afterPtr);

Учитывая это ограничение, я бы выбрал чисто Python-подход, например, использование Timer :

import time
import threading
import tkinter as tk

root = tk.Tk()

def say_hi():
    print(time.perf_counter(), "-", "Hi after 30sec!")
    root.destroy()

print(time.perf_counter(), "-", "Waiting 30sec")
threading.Timer(30, say_hi).start()
root.mainloop()

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

1 голос
/ 27 апреля 2019

Объяснение

Как вы и подозревали, при использовании .after() tkinter означает планирование событие, которое должно произойти в current_time + delay_ms.Это означает, что если системное время изменяется между этими событиями, это подорвет запланированное событие.

Это основано на том факте, что tkinter просто вызывает команду after tcl (основная система, с которой общается tkinter). tcl docs скажите нам:

after использует системное время для определения времени наступления запланированного события.Это означает, что , за исключением после 0 и после простоя , может быть нарушено изменениями системного времени.

Теперь обратите внимание, что after idle освобождается от системысвязь с часами, а также after 0, но они, вероятно, не являются хорошей заменой для вас.


после 0

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

Таким образом, используя after 0не будет оптимальным, поскольку он находится в начале очереди событий, что означает, что больше ничего не произойдет.


после простоя

Это аналогично освобождено, но, вероятно,тоже не будет лучше [docs]

Сценарий будет запущен ровно один раз, при следующем входе в цикл обработки событий и событий для обработки не будет.

Таким образом, сценарий будет запускаться, когда следующая система станет бездействующей.Вы можете использовать after x с after idle, и это подождет, пока события не очистятся и система не будет работать, затем подождите x миллисекунд перед выполнением этой команды, но я подозреваю, что это не то, что вы хотите сделать.


Tl; dr

Итак, к вашему последнему вопросу, что вы можете сделать, если можно было ожидать, что часы перевернутся?Родной для Ткинтер: не сильно.Если вы не уловили обратное и не сбросили событие after() или не написали свой собственный планировщик событий на основе time.process_time() (ранее time.clock()), я не вижу способа заставить .after() работать по-другому.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...