Скорость таймера обратного отсчета увеличивается, когда я несколько раз нажимаю кнопку пуска и паузы в tkinter - PullRequest
0 голосов
/ 23 мая 2019

У меня есть сценарий обратного отсчета, в котором секунды обновляются быстро, когда я нажимаю кнопки «Пуск» и «Пауза» несколько раз один за другим.

Сначала я подумал, что быстрое нажатие между кнопками «Пуск» и «Пауза» ускоряет секунды, поэтому я добавил time.sleep(1) чтобы задержать нажатие между кнопками, которые не работали.

Как я могу решить эту проблему?

Правильно ли работает мой алгоритм?Или есть другой лучший способ сделать время обратного отсчета?Если да, как я могу это сделать?

КОД

from tkinter import *

PAUSE = False
HOUR, MINUTE, SECOND = 0, 0, 0


def start():
    '''Command for START button'''

    global PAUSE

    PAUSE = False
    start_button['state'] = 'disabled'
    pause_button['state'] = 'normal'
    reset_button['state'] = 'normal'
    # time.sleep(1) to delay time between clicks of pause and start buttons
    Counter()


def pause():
    '''Command for PAUSE button'''

    global PAUSE

    PAUSE = True
    start_button['state'] = 'normal'
    pause_button['state'] = 'disabled'


def reset():
    '''Command for RESET button'''

    global HOUR, MINUTE, SECOND, PAUSE

    PAUSE = True
    start_button['state'] = 'normal'
    pause_button['state'] = 'disabled'
    reset_button['state'] = 'disabled'
    Time['text'] = '00:00:00'

    HOUR, MINUTE, SECOND = 0, 0, 0


def Counter():
    '''Updating hour, minute and seconds'''

    global HOUR, MINUTE, SECOND

    if PAUSE is False:
        if SECOND == 59:
            if MINUTE == SECOND == 59:
                HOUR += 1

            if MINUTE == 59:
                MINUTE = 0

            else:
                MINUTE += 1

            SECOND = -1

        SECOND += 1

        Time.config(text='{}:{}:{}'.format(str(HOUR).zfill(2), str(MINUTE).zfill(2), str(SECOND).zfill(2)))
        root.after(1000, Counter)


root = Tk()
root.title('COUNTER')

width, height = 342, 108
pos_x = root.winfo_screenwidth() // 2 - width // 2
pos_y = root.winfo_screenheight() // 2 - height // 2

root.geometry('{}x{}+{}+{}'.format(width, height, pos_x, pos_y))

Time = Label(root, fg='Black', text='00:00:00', font=("Helvetica", 40))
Time.pack(side='bottom')

start_button = Button(root, text='START', font=("Arial", 16), fg='black', width=8, command=start)
start_button.pack(side='left')

pause_button = Button(root, text='PAUSE', font=("Arial", 16), fg='black', width=8, state='disabled', command=pause)
pause_button.pack(side='left')

reset_button = Button(root, text='RESET', font=("Arial", 16), fg='black', width=10, state='disabled', command=reset)
reset_button.pack(side='left', fill='both')

root.mainloop()

Ответы [ 2 ]

1 голос
/ 23 мая 2019

Сначала я подумал, что быстрое нажатие между кнопками запуска и паузы ускоряет секунды, поэтому я добавил time.sleep (1), чтобы задержать нажатие между кнопками, которые не работали.

Проблема заключается в том, что из-за задержки перед тем, как метод .aftert() перезвонит сам себе, несколько раз нажмите кнопку запуска и создайте несколько циклов .after(1000, counter). Это означает, что одновременно происходит много циклов .after(). Чтобы это исправить, вам просто нужно сделать так, чтобы кнопка запуска не могла быть нажата, если происходит цикл .after().

Для этого вы должны изменить три свои функции

Функция counter()

Я изменил код, поэтому, если счетчик работает, start_button будет отключен, а когда счетчик остановится, его состояние вернется к нормальному состоянию

def Counter():
    '''Updating hour, minute and seconds'''
    global HOUR, MINUTE, SECOND

    if PAUSE is False:
        start_button['state'] = 'disabled' # setting it to disabled if the counter is running
        if SECOND == 59:
            if MINUTE == SECOND == 59:
                HOUR += 1

            if MINUTE == 59:
                MINUTE = 0

            else:
                MINUTE += 1

            SECOND = -1

        SECOND += 1

        Time.config(text='{}:{}:{}'.format(str(HOUR).zfill(2), str(MINUTE).zfill(2), str(SECOND).zfill(2)))
        root.after(1000, Counter)
    else:
        start_button['state'] = 'normal' # setting it to normal if the counter stops

Функции pause() и reset()

Вы должны удалить возможность установить состояние start_button в нормальное состояние, поскольку это позволит нажать start_button до того, как завершится последний цикл счетчика

def pause():
    '''Command for PAUSE button'''

    global PAUSE

    PAUSE = True
    pause_button['state'] = 'disabled'

def reset():
    '''Command for RESET button'''

    global HOUR, MINUTE, SECOND, PAUSE

    PAUSE = True
    pause_button['state'] = 'disabled'
    reset_button['state'] = 'disabled'
    Time['text'] = '00:00:00'

    HOUR, MINUTE, SECOND = 0, 0, 0

Обновление этих функций устранит эту ошибку. Надеюсь, что это ответ, который вы искали:)

1 голос
/ 23 мая 2019

Ваша Counter функция вызывает root.after(1000,Counter) каждый щелчок, а также изменяет метку Time сразу после нажатия. Когда вы нажимаете кнопки достаточно быстро, вы можете запланировать несколько root.after, а также суммировать секунды.

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

from tkinter import *

PAUSE = False
HOUR, MINUTE, SECOND = 0, 0, 0
action = None #keep track on current action and also avoid click spam


def start():
    '''Command for START button'''

    global PAUSE, action

    PAUSE = False
    ...
    if not action:
        Counter()


def pause():
    '''Command for PAUSE button'''

    global PAUSE, action

    ...
    if action:
        root.after_cancel(action)
        action = None


def reset():
    '''Command for RESET button'''

    global HOUR, MINUTE, SECOND, PAUSE, action

    ...

    HOUR, MINUTE, SECOND = 0, 0, 0
    action = None


def Counter():
    '''Updating hour, minute and seconds'''

    global HOUR, MINUTE, SECOND, action

    if PAUSE is False:
        if SECOND == 59:
            if MINUTE == SECOND == 59:
                HOUR += 1

            if MINUTE == 59:
                MINUTE = 0

            else:
                MINUTE += 1

            SECOND = -1

        SECOND += 1

        Time.config(text='{}:{}:{}'.format(str(HOUR).zfill(2), str(MINUTE).zfill(2), str(SECOND).zfill(2)))
        action = root.after(1000, Counter)

root = Tk()
...
start_button = Button(root, text='START', font=("Arial", 16), fg='black', width=8, command=lambda: root.after(1000,start)) #to avoid the instant second increment
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...