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

2024-06-17 08:40:41 发布

您现在位置:Python中文网/ 问答频道 /正文

这是一款生命游戏应用程序,使用after来减缓细胞在出生、生命、死亡等阶段的动画

与after的耦合问题:

1.我已经对Tkinter进行了广泛的研究,这篇文章捕获了我发现的最清晰的说明regarding after with parameters,然而,我的Tkinter应用程序不起作用-根据已经收到的评论,可能不是在后面,但这就是症状出现的地方? 2.基本上,当我没有将参数放入after(例如。小工具.after(200, self.my\u函数,参数1,参数2,…)不迭代。但是,当我做了同样的操作,但将参数括起来时,它会按预期进行迭代(例如。小工具.after(200, self.my\u函数(参数1,参数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))

布莱恩,你问了一个错误的例子。为了显示错误,我在调用函数中添加了一些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

我是一个业余爱好者,没有受过正规的培训,所以我肯定我忽略了一些基本的东西,包括如何最好的研究我自己。但我很感激你的建议。你知道吗


Tags: andthekeyself参数leniscounter
2条回答

我建议两者都不要:

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()的定义:

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)

问题是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))

相关问题 更多 >