为什么清除和重写此 tkinter 框架会使其重复?

Why does clearing and rewriting this tkinter frame make it duplicate?

我正在使用 Python 中的 tkinter 模块开发 RPG 风格的游戏,我有一个角色创建屏幕,其中包含随机生成的统计数据。这 6 个统计数据是使用 random 模块生成的。

我遇到的问题是,当我清除屏幕以将数字重新打包到专用于它们的框架中时,它第一次起作用了,数字被清除并出现了一组新数字,但是第二个和第三个时间(等等)我按下按钮它只会在框架内生成一组新的数字,而以前的数字仍然存在,复制数字的数量。

我尝试了 运行 从该站点看到的各种不同方法,例如 .pack_forget 和从屏幕上删除,我什至将用于存储标签的变量设置为 None但我似乎没有任何尝试。

我会post下面的代码,程序有几百行,如果我遗漏了与问题相关的任何内容,请原谅我。

def CharManage2Option3Command(StrengthValue, DexterityValue, ConstitutionValue, WisdomValue, IntelligenceValue, CharismaValue, statframebottomleftright, statframebottomrightright):
    StrengthValue.destroy()
    DexterityValue.destroy()
    ConstitutionValue.destroy()
    WisdomValue.destroy()
    IntelligenceValue.destroy()
    CharismaValue.destroy()
    StrNumber = randrange(3, 18)
    DexNumber = randrange(3, 18)
    ConNumber = randrange(3, 18)
    WisNumber = randrange(3, 18)
    IntNumber = randrange(3, 18)
    ChaNumber = randrange(3, 18)
    StrengthValue = Label(statframebottomleftright, text=StrNumber, fg=DefaultColour, bg=WhiteBackgroundColour, font=DefaultFont)
    DexterityValue = Label(statframebottomleftright, text=DexNumber, fg=DefaultColour, bg=WhiteBackgroundColour, font=DefaultFont)
    ConstitutionValue = Label(statframebottomleftright, text=ConNumber, fg=DefaultColour, bg=WhiteBackgroundColour, font=DefaultFont)
    WisdomValue = Label(statframebottomrightright, text=WisNumber, fg=DefaultColour, bg=WhiteBackgroundColour, font=DefaultFont)
    IntelligenceValue = Label(statframebottomrightright, text=IntNumber, fg=DefaultColour, bg=WhiteBackgroundColour, font=DefaultFont)
    CharismaValue = Label(statframebottomrightright, text=ChaNumber, fg=DefaultColour, bg=WhiteBackgroundColour, font=DefaultFont)
    StrengthValue.pack(fill="both", expand=True)
    DexterityValue.pack(fill="both", expand=True)
    ConstitutionValue.pack(fill="both", expand=True)
    WisdomValue.pack(fill="both", expand=True)
    IntelligenceValue.pack(fill="both", expand=True)
    CharismaValue.pack(fill="both", expand=True)

您遇到的问题是作业,例如StrengthValue = Label(...) 函数内部 不会 影响传入的对象,它只是将新对象分配给该名称 函数内部 .因此,您第一次调用该函数时,原始对象会按预期进行 destroyed,但您不会保留对新对象的引用(因为它们不是从函数中 returned)所以后续调用似乎行为不正确。

一种解决方案是传递可变参数,例如包含相关对象的列表:

def CharManage2Option3Command(label_lists, stat_frames):
    for label_list, stat_frame in zip(label_lists, stat_frames):
        for index, label in enumerate(label_list):
            number = randrange(3, 18)
            label.destroy()
            label_list[index] = Label(stat_frame, text=number, ...)
            label_list[index].pack(...)

(请参阅 zip and enumerate 上的文档。)。这将被称为例如:

CharManage2Option3Command([[StrengthValue, DexterityValue, ConstitutionValue], 
                           [WisdomValue, IntelligenceValue, CharismaValue]],
                          [statframebottomleftright, statframebottomrightright]):

请注意,这具有减少函数重复的便利副作用。您还可以从一开始就将 Label 个实例保存在一个列表中,而不是对每个实例单独进行引用。


其他解决方案包括显式 return 从函数中获取新标签并重新分配给原始名称:

def CharManage2Option3Command(StrengthValue, DexterityValue, ConstitutionValue, WisdomValue, IntelligenceValue, CharismaValue, statframebottomleftright, statframebottomrightright):
    ...
    return StrengthValue, DexterityValue, ConstitutionValue, WisdomValue, IntelligenceValue, CharismaValue

然后调用它:

StrengthValue, DexterityValue, ConstitutionValue, WisdomValue, IntelligenceValue, CharismaValue = CharManage2Option3Command(StrengthValue, DexterityValue, ConstitutionValue, WisdomValue, IntelligenceValue, CharismaValue, statframebottomleftright, statframebottomrightright)

(这显然很尴尬),使用 IntVar 作为 Labeltextvariable 并更新它或做一些基于 class 的事情,这样你访问例如self.StrengthValue无处不在。


我还建议您看一下 style guide,它提供了函数和变量名称等方面的约定。