【问题标题】:'Nonetype' object not callable when calling animation of object in tkinter [closed]在 tkinter 中调用对象动画时,“Nonetype”对象不可调用 [关闭]
【发布时间】:2025-12-10 19:50:02
【问题描述】:

我一直用这个作为模板:

Blobs Animation

几乎我能找到的唯一区别是他使用了这条线:

from Tkinter import *

而我使用这条线

import Tkinter as Tk

我认为我通过将所有对 Tkinter 模块的调用都作为 Tk.(Blob.py 等效项)来解释这一点。我可以运行这个 blob 动画示例,但我的程序出现错误:

'Nonetype' object not callable

上线:

allStars[i] = allStars[i]()

来自我下面的代码(这一行在最后一段代码中):

class Star:

    def __init__(self, canvas, xy, delta):

        self.canvas = canvas
        self.delta = delta

        self.id = self.canvas.create_rectangle(
            xy[0],xy[1],
            xy[0]+starSize,xy[1]+starSize,
            fill='white'
            )


    def __call__(self):
        return self.down

    def down(self):

        xy = self.canvas.coords(self.id)
        if xy[1] >= gameScreenHeight:
            x2 = random.randint(1,gameScreenWidth)
            y2 = 0;
            self.canvas.coords(self.id,x2,y2)
        else:
            self.canvas.move(self.id, 0, self.delta)


root = Tk.Tk()
root.title("Stars")
root.resizable(0,0)
TkPlacement = "%dx%d%+d%+d" % (gameScreenWidth, gameScreenHeight, 10*starSize, heightOffset)
root.geometry(TkPlacement)

frame = Tk.Frame(root, bd = 5, relief=Tk.SUNKEN)
frame.pack()

space = Tk.Canvas(frame, width = gameScreenWidth, height = gameScreenHeight, cursor = 'plus')
space.pack()
space.create_rectangle(0,0,gameScreenWidth,gameScreenHeight,fill="black")



allStars = [
    Star(space, (10,30),3),
    Star(space, (15,60),3),
    Star(space, (80,50),5)
    ]

#N = 99;

#for i in range(N):
#   x1 = random.randint(1,gameScreenWidth)
#   y1 = random.randint(1,gameScreenHeight)
#   aStar = Star(space, (x1,y1), 3)
#   allStars.append(aStar)

root.update()

try:
    while 1:
        for i in range(len(allStars)):
            allStars[i] = allStars[i]()
            root.update_idletasks() # redraw
        root.update() # process events
except Tk.TclError:
    pass # to avoid errors when the window is closed

【问题讨论】:

    标签: python animation tkinter


    【解决方案1】:

    在代码的早期,您将 allStars[i] 设置为函数 (self.done)。此函数返回None,因为没有明确的返回语句。

    当你这样做时:

    allStars[i] = allStars[i]()
    

    ...您将allStars[i] 的值替换为调用allStars[i] 的结果,即None。下次执行这行代码时,allStars[i]None,所以你会得到那个错误。

    如果您尝试制作动画,有比运行自己的无限循环更好的方法,因为您已经运行了无限循环 -- mainloop。例如,您可以使用以下代码删除整个 while 循环和 try/catch 块:

    def redraw():
        for i in range(len(items)):
            items[i] = items[i]()
        root.after(int(1000/30), redraw) # 30 frames per second
    
    root.after_idle(redraw)
    root.mainloop()
    

    【讨论】:

    • 感谢您的回答。在 blobs 示例中,作者省略了 mainloop 函数并使用了 while 循环。我认为这是为了将来考虑同步,但这只是基于我所读到的关于 Tkinter 同步困难的内容。我是 python 新手,所以我主要只是按照作者的例子,还没有完全理解我所做的一切。
    • “同步困难”?这意味着什么?我没有意识到没有调用mainloop。这是使用 Tkinter 的一种非常奇怪的方式,不推荐使用。您使用的示例是如何使用 tkinter 制作动画的一个糟糕示例。
    • 我找不到具体的参考资料,但人们基本上说 pygame 优于 tkinter,因为它会自动处理同步,而 tkinter 需要更仔细的注意。我选择 Tkinter 是因为我个人更喜欢在可能的情况下使用标准库,而 pygame 的缺点(所以我读过)是它可能很慢而且很笨重。我不确定我会用什么替换 mainloop。
    • 顺便问一下,您知道使用更好标准的更好的动画示例吗?
    • @Xurtio:见*.com/a/11505034/7432
    【解决方案2】:

    down() 返回None(隐式);第一次通过无限循环,您将用它替换 allStars 中的所有内容。

    allStars[i] = allStars[i]() 可能不是您想要的,尽管您还不清楚您想用它来完成什么。

    【讨论】:

    • 啊,我明白了。他在我完全忽略的调用函数中使用了返回。谢谢。
    最近更新 更多