使用参数导致函数挂起后调用tkinter

时间:2018-12-24 15:53:09

标签: python tkinter

这是一款用于生活游戏的应用程序,用于在出生,生命,死亡等各个阶段之后延缓细胞的动画。

加上以下问题:

1。我一直在广泛研究Tkinter,这篇文章捕捉了我发现的最清晰的说明regarding after with parameters,但是,我对Tkinter的应用无法正常工作-基于已经收到的评论,可能不是以后的事,而是那是症状出现的地方? 2.当我不将参数放在after内部的括号中时(例如widget.after(200,self.my_function,parameter 1,parameter 2,....)不但是,当我执行同样的操作但将参数括起来时,它会按预期进行迭代(例如,widget.after(200,self.my_function(parameter 1,parameter 2,....))。

3。但是,使用括号中的参数运行时,after会挂起。下面的代码中的列表包含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))

布莱恩,您曾要求提供错误示例。为了显示错误,我在调用函数中添加了一些打印语句,然后解释了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 :(得分:1)

您的问题将是由root.after(200, self.repeat_colors(temp_cells, counter))引起的无限循环。相反,您需要将self.repeat_colors作为lambda传递。

因此,正在发生self.repeat_colors(temp_cells, counter)的即时调用,而不是等待200秒。因此,请创建一个lambda函数,该函数将等到设置的时间激活。

请牢记lambda表达式,如果您更改的值需要在lambda中定义它。因此,对于计数器,您需要执行类似x=counter的操作,因此lambda一定会使用正确的更新值。通常,这会影响诸如创建lambda表达式的循环之类的事情,在这种特定情况下可能无关紧要,但是在重要的时候习惯练习。

更改此:

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

对此:

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

答案 1 :(得分:1)

我都不建议:

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)