tkinter после вызова функции с параметрами, вызывающими зависание функции - PullRequest
0 голосов
/ 24 декабря 2018

Это приложение для игры из жизни, использующее после для замедления анимации клеток на этапах рождения, жизни, смерти и т. Д.

Проблемы с парой после:

1. Я проводил тщательное исследование Tkinter, и в этом посте собраны самые четкие инструкции, которые я нашел в отношении после с параметрами , однако мое приложение Tkinter не работает - основываясь на уже полученных комментариях, вероятно, не послено вот где появляются симптомы?2.Basally, кажется, не работает вообще, когда я не помещаю параметры в круглые скобки внутри after (например, widget.after (200, self.my_function, параметр 1, параметр 2, ....) не делаетитерации. Однако, когда я делаю то же самое, но заключаю параметры, он выполняет итерацию, как и предполагалось (например, widget.after (200, self.my_function (параметр 1, параметр 2, ....)).

3.Однако при запуске с параметрами в круглых скобках зависание после. Список в приведенном ниже коде содержит 81 элемент, и не случайно функция зависает на 16,2 секунды ...

Код выглядит следующим образом:

 def color_cells(
           self, 
           cells, 
           repeater, 
           temp_cells=0, 
           counter=0, 
           after_id=None
           ):

    global paused

    if temp_cells != 0:

        self.repeat_colors(temp_cells)
        temp_cells.clear()
        temp_cells = 0
        for key in cells:
            if cells[key][0] == 'emerging':
                cells[key] = 'active', colors['active'][1]
            if cells[key][0] == 'dying':
                cells[key] = 'inactive', colors['inactive'][1]
        counter = 0
        if repeater and not paused:
            print("repeater is ", repeater, " and paused is ",paused)
            self.id_changes(cells)
        else:
            self.closeoutGame()

    else:

    try:
       print("made it to the else in color_cells and repeater is ",repeater, " and length of temp cells list is ", len(temp_cells))

    except:
       print("made it to the else in color_cells and repeater is ",repeater, " and temp cells is empty")

        for key in cells:
            color_rectangle = self.canvas_manager.find_withtag(key)
            self.canvas_manager.itemconfigure(color_rectangle, fill = cells[key][1])
            self.canvas_manager.update()



def repeat_colors(self, temp_cells, counter=0):
    print("starting repeat colors and the temps cells len is ", len(temp_cells), " and the counter is ",counter)
    if counter < len(temp_cells):
        color_rectangle = self.canvas_manager.find_withtag(temp_cells[counter][0])
        self.canvas_manager.itemconfigure(color_rectangle, fill = temp_cells[counter][1])
        self.canvas_manager.update()
        counter = counter + 1
        root.after(200, self.repeat_colors(temp_cells, counter))

Брайан, вы запросили пример ошибки. Чтобы показать ошибку, я добавил несколько операторов print в вызывающую функцию и затем объяснил, где начинается 16,2-секундный период бездействия:

 starting repeat colors and the temps cells len is  81  and the counter is  0
 starting repeat colors and the temps cells len is  81  and the counter is  1
 starting repeat colors and the temps cells len is  81  and the counter is  2
 ...
 starting repeat colors and the temps cells len is  81  and the counter is  79
 starting repeat colors and the temps cells len is  81  and the counter is  80
 starting repeat colors and the temps cells len is  81  and the counter is  81

 ...hangs for the 16.2 seconds, equal to 200 ms x 81 iterations

Я - любитель и не имею формального обучения, и поэтому я уверен, что упускаю из виду кое-что базовое здесь, включая то, как лучше всего исследовать самостоятельно. Но я ценю любой совет.

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

Я бы не предложил ни:

root.after(200, self.repeat_colors(temp_cells, counter))

, ни:

root.after(200, lambda x=counter: self.repeat_colors(temp_cells, x))

, а скорее:

root.after(200, self.repeat_colors, temp_cells, counter)

Это неправильное понимание after() Я вижучасто и имел себя.Определение after():

после (ms, func = None, * args)

Call function once after given time.

MS specifies the time in milliseconds. FUNC gives the
function which shall be called. Additional parameters
are given as parameters to the function call.  Return
identifier to cancel scheduling with after_cancel.

Код, который вы разместили с помощью вышеуказанного исправления и других настроек- к сожалению, трудно обойтись без MCVE :

def color_cells(self, cells, repeater, temp_cells=None, counter=0):

    if temp_cells is not None:

        self.repeat_colors(temp_cells)
        temp_cells.clear()
        temp_cells = None

        for key in cells:
            if cells[key][0] == 'emerging':
                cells[key] = 'active', colors['active'][1]
            if cells[key][0] == 'dying':
                cells[key] = 'inactive', colors['inactive'][1]

        counter = 0

        if repeater and not paused:
            print("repeater is", repeater, "and paused is", paused)
            self.id_changes(cells)
        else:
            self.closeoutGame()
    else:
        print("Made it to the else in color_cells and repeater is", repeater, "and temp cells is empty")

        for key in cells:
            color_rectangle = self.canvas_manager.find_withtag(key)
            self.canvas_manager.itemconfigure(color_rectangle, fill=cells[key][1])
            self.canvas_manager.update()

def repeat_colors(self, temp_cells, counter=0):
    print("Starting repeat colors and the temps cells len is", len(temp_cells), "and the counter is", counter)

    if counter < len(temp_cells):
        color_rectangle = self.canvas_manager.find_withtag(temp_cells[counter][0])
        self.canvas_manager.itemconfigure(color_rectangle, fill=temp_cells[counter][1])
        self.canvas_manager.update()
        counter += 1
        root.after(200, self.repeat_colors, temp_cells, counter)
0 голосов
/ 24 декабря 2018

Ваша проблема - бесконечный цикл, вызванный root.after(200, self.repeat_colors(temp_cells, counter)).Вместо этого вам нужно передать ваш self.repeat_colors как лямбду.

Так что происходит то, что self.repeat_colors(temp_cells, counter) вызывается мгновенно, вместо ожидания 200 секунд.Поэтому вместо этого создайте лямбда-функцию, которая будет ждать до установленного времени для активации.

Помните о лямбда-выражениях, если у вас есть значение, которое нужно изменить, вам нужно определить его в лямбда-выражении.Поэтому для счетчика нужно сделать что-то вроде x=counter, чтобы лямбда-код обязательно использовал правильное обновленное значение.Обычно это влияет на такие вещи, как циклы, которые создают лямбда-выражения, и, вероятно, не имеет значения в данном конкретном случае, но является хорошей привычкой для практики, когда это имеет значение.

Измените это:

root.after(200, self.repeat_colors(temp_cells, counter))

На это:

root.after(200, lambda x=counter: self.repeat_colors(temp_cells, x))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...