Python 3.3 和 TKinter,错误信息和崩溃

Python 3.3 and TKinter, error message and crash

作为一种爱好,我喜欢涉足 Python 这个东西。我正在尝试制作一个简单的程序来帮助我心爱的妻子追踪和识别食物敏感性。我已经有了一个可用的版本,但出于无聊,我试图通过在主屏幕上添加一个小的自动收报机小部件来改进它。这样做后,我发现了一个我无法弄清楚的错误。我什至不确定它想诚实地告诉我什么。但是每当我从主菜单中单击 "Next" 按钮时,它就会发生。

我的代码:

from tkinter import *
import os, shelve


class Food:

    def __init__(self, name, score):
        self.name = name
        self.score = score


class Main:

    def __init__(self, master):
        self.master = master
        self.master_frame = Frame(self.master)
        self.master_frame.pack()
        self.home_frame()

    def home_frame(self):
        for child in self.master_frame.winfo_children():
            child.destroy()    
        self.ticker = ' ' * 29
        self.start = 0
        self.end = 29
        for i in catalog.values():
            self.ticker = self.ticker + str(i.name) + ': ' + str(i.score) + '%' + ' ' * 10
        print(self.ticker)
        self.create_widgets()

    def create_widgets(self):

        self.ticker_frame = Frame(self.master_frame, bd = 5, bg = 'black')
        self.ticker_label = Label(self.ticker_frame, text = '<empty>', fg = 'white', bg = 'black')
        self.ticker_label.grid(row = 0, columnspan = 3, sticky = E + W)
        self.ticker_frame.pack(expand = 1, fill = 'x', anchor = 'center')

        self.button_frame = Frame(self.master_frame, bd = 5, bg = 'black')
        Button(self.button_frame, text = 'Next', width = 10, command = self.next_win).grid(row = 0, column = 0)
        Button(self.button_frame, text = 'N/A', width = 10, command = self.master.destroy).grid(row = 0, column = 1)
        Button(self.button_frame, text = 'Exit', width = 10, command = self.master.destroy).grid(row = 0, column = 2)
        self.button_frame.pack()

        self.run_ticker()

    def run_ticker(self):
        ticker_text = self.ticker[self.start:self.end]
        self.ticker_label.config(text = ticker_text, font = ('courier', 10, 'bold'))
        self.start += 1
        self.end += 1
        if self.start == len(self.ticker):
            self.start = 0
            self.end = 29
        self.master.after(250, self.run_ticker)

    def next_win(self):
        for child in self.master_frame.winfo_children():
            child.destroy()
        self.next_frame = Frame(self.master_frame)
        new_label = Label(self.next_frame, text = 'Blah...').grid()
        Button(self.next_frame, text = 'Main', command = self.home_frame).grid()
        self.next_frame.pack()




x = Food('Grapes', 50)
y = Food('Cheese', 75)
z = Food('Eggs', 35)

catalog = {}

catalog[x.name] = x
catalog[y.name] = y
catalog[z.name] = z



root = Tk()
Main(root)

root.mainloop()

我收到的错误消息,两个按钮都一样:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python33\lib\tkinter\__init__.py", line 1442, in __call__
    return self.func(*args)
  File "C:\Python33\lib\tkinter\__init__.py", line 501, in callit
    func(*args)
  File "C:\Users\Gregory\Desktop\Test2 Working except ticker.pyw", line 111, in run_ticker
    self.ticker_label.config(text = ticker_text, font = ('courier', 10, 'bold'))
  File "C:\Python33\lib\tkinter\__init__.py", line 1230, in configure
    return self._configure('configure', cnf, kw)
  File "C:\Python33\lib\tkinter\__init__.py", line 1221, in _configure
    self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: invalid command name ".52922632.52924032"

先生奥克利在回答我之前的一个问题时非常雄辩地说 "unless you know what is going on under the hood..." 而我显然没有,这就是为什么我不知道 shell 试图告诉我什么。

另外,一个不太重要的问题: 我试图将程序的主菜单保留在屏幕的右上角。我的尝试失败了。它从右上角初始化,然后在打开一个新的 window 时它会正确移动,最后返回主菜单时它会落到正确的位置。显然我在这里也遗漏了一些东西。

一如既往的感谢!

你有一个毁灭

def next_win(self):
    for child in self.master_frame.winfo_children():
        child.destroy()

其中包含 ticker_frame 及其所有小部件,因此 run_ticker() 中的 after 语句在框架被销毁后仍在调用该函数。在创建框架时使用一些变量,例如 self.is_tinker_frame = True,在销毁框架时将其设置为 False 加上:

if self.is_tkinter_frame:
    self.master.after(250, self.run_ticker)

此外,在变量设置为 False 后等待超过 250 分钟以破坏框架,以允许完成任何调用。