【问题标题】:Why I cannot create a class object inside a function?为什么我不能在函数内创建类对象?
【发布时间】:2019-05-28 16:46:27
【问题描述】:

我的主代码包含多个函数,我对其进行了测试,它运行良好。然后我为tkinter 窗口创建一个类,并单独对其进行测试,它也可以正常工作。当我将它们合并在一起时,通过在函数中创建一个类对象,我收到以下错误消息:

"TclError: can't invoke "frame" command: application has been destroyed"

import tkinter

class InputFromForm():
    def __init__(self, root, values):
        self.field = []
        self.fieldStrings = values
        self.temp = self.makeform(self.fieldStrings)

    def makeform(self, fields):
        entries = []
        for i in fields:
            row = tkinter.Frame(root)
            lab = tkinter.Label(row, width=15, text=i, anchor='w')
            ent = tkinter.Entry(row)
            ent.insert(tkinter.END, fields[i])
            ent.bind("<FocusIn>", lambda event, e=ent: e.selection_range(0, tkinter.END))
            row.pack(side=tkinter.TOP, fill=tkinter.X, padx=5, pady=10)
            lab.pack(side=tkinter.LEFT)
            ent.pack(side=tkinter.RIGHT, expand=tkinter.YES, fill=tkinter.X)
            entries.append((i, ent))

        return entries


    def fetch(self, entries):
        for entry in entries:
            string = entry[0]
            text  = entry[1].get()
            self.field.append(text)
        return self.field

    def close(self, root):
        root.destroy()


def extractData(dOfValues):
    root = tkinter.Tk()
    root.title('Test')
    userInput = InputFromForm(root, dOfValues)
    root.bind('<Return>', (lambda event, e=userInput.temp: userInput.fetch(e)))
    b1 = tkinter.Button(root, text='OK',command=(lambda e=userInput.temp: [userInput.fetch(e), userInput.close(root)]))
    b1.config(width=25)
    b1.pack(anchor=tkinter.CENTER, padx=5, pady=20)


    root.mainloop()



if __name__ == '__main__':


    dOfValues = {'Customer No.': '',
            'PO #':'020202',
            'Order Date': '2/3/2012',
            'Zip to code':'92182'}

    #root = tkinter.Tk()
    #root.title('Test')

    #userInput = InputFromForm(root, dOfValues)

    #root.bind('<Return>', (lambda event, e=userInput.temp: userInput.fetch(e)))
    #b1 = tkinter.Button(root, text='OK',command=(lambda e=userInput.temp: [userInput.fetch(e), userInput.close(root)]))
    #b1.config(width=25)
    #b1.pack(anchor=tkinter.CENTER, padx=5, pady=20)


    #root.mainloop()
    extractData(dOfValues)  # Adding this, creates the error. If I put the code 
                            # from this function into main, it works. 

有人能解释一下是怎么回事吗?

【问题讨论】:

  • 您似乎遇到了编码错误。你从来没有真正在你的课堂上保存根目录。你需要做self.root = root。然后row = tkinter.Frame(self.root)。它真的应该只给你一个 NameError,但也许 Tkinter 有一些错误捕捉到,这会混淆错误。
  • 这个错误是不言自明的。有一次你有一个根窗口,它被破坏了,现在你试图在一个不再存在的窗口中创建一个框架。
  • @Greg 我添加了你推荐的内容,我相信我的close() 方法应该是:self.root.destroy()。我遇到了另一个错误:"AttributeError: 'InputFromForm' object has no attribute 'root'".
  • @BryanOakley 根窗口是如何被破坏的?我从来没有把它毁掉
  • 你认为第 23 行中的 root.destroy() 有什么作用?

标签: python class tkinter


【解决方案1】:

@paul "打印和返回完全不相关"

你确定吗?试试这个代码。我想你可以改变它来检索什么

你想要的,你的字段值,如果我明白你想要什么的话。

import tkinter as tk
from tkinter import messagebox

class InputFromForm(tk.Tk):
    def __init__(self, root, values):
        self.field = []
        self.entries = []
        self.fieldStrings = values
        self.temp = self.makeform(self.fieldStrings)

    def makeform(self, fields):

        entries = []

        for i in fields:
            row = tk.Frame()
            lab = tk.Label(row, width=15, text=i, anchor='w')
            ent = tk.Entry(row)
            ent.insert(tk.END, fields[i])
            ent.bind("<FocusIn>", lambda event, e=ent: e.selection_range(0, tk.END))
            row.pack(side=tk.TOP, fill=tk.X, padx=5, pady=10)
            lab.pack(side=tk.LEFT)
            ent.pack(side=tk.RIGHT, expand=tk.YES, fill=tk.X)
            entries.append((i, ent))

        return entries 


    def fetch(self, entries):
        for entry in entries:
            string = entry[0]
            text  = entry[1].get()
            self.field.append(text)
        return self.field

    def close(self, root):

        msg = "Do you want to quit?\nI've this data for you\n {0}".format(self.field)

        if messagebox.askokcancel("Simple App", msg):
            root.destroy()



def extractData(dOfValues):
    root = tk.Tk()
    root.title('Test')
    userInput = InputFromForm(root, dOfValues)
    root.bind('<Return>', (lambda event, e=userInput.temp: userInput.fetch(e)))
    b1 = tk.Button(root, text='OK',command=(lambda e=userInput.temp: [userInput.fetch(e), userInput.close(root)]))
    b1.config(width=25)
    b1.pack(anchor=tk.CENTER, padx=5, pady=20)


    root.mainloop()

if __name__ == '__main__':


    dOfValues = {'Customer No.': '',
            'PO #':'020202',
            'Order Date': '2/3/2012',
            'Zip to code':'92182'}

    #root = tk.Tk()
    #root.title('Test')

    #userInput = InputFromForm(root, dOfValues)

    #root.bind('<Return>', (lambda event, e=userInput.temp: userInput.fetch(e)))
    #b1 = tk.Button(root, text='OK',command=(lambda e=userInput.temp: [userInput.fetch(e), userInput.close(root)]))
    #b1.config(width=25)
    #b1.pack(anchor=tk.CENTER, padx=5, pady=20)


    #root.mainloop()
    extractData(dOfValues)  # Adding this, creates the error. If I put the code 
                            # from this function into main, it works. 

【讨论】:

  • 是的,我要评论你之前的帖子,它有效,我的错。
【解决方案2】:

我不太确定问题出在哪里,但是我做了一些改变

在您的脚本上。首先我将 tkinter 作为 tk 导入,然后我继承了你的

来自 Tk 的类,见下文。

import tkinter as tk

class InputFromForm(tk.Tk):
    def __init__(self, root, values):
        self.field = []
        self.fieldStrings = values
        self.temp = self.makeform(self.fieldStrings)

    def makeform(self, fields):
        entries = []
        for i in fields:
            row = tk.Frame()
            lab = tk.Label(row, width=15, text=i, anchor='w')
            ent = tk.Entry(row)
            ent.insert(tk.END, fields[i])
            ent.bind("<FocusIn>", lambda event, e=ent: e.selection_range(0, tk.END))
            row.pack(side=tk.TOP, fill=tk.X, padx=5, pady=10)
            lab.pack(side=tk.LEFT)
            ent.pack(side=tk.RIGHT, expand=tk.YES, fill=tk.X)
            entries.append((i, ent))

        return entries


    def fetch(self, entries):
        for entry in entries:
            string = entry[0]
            text  = entry[1].get()
            self.field.append(text)
        return self.field

    def close(self, root):
        root.destroy()


def extractData(dOfValues):
    root = tk.Tk()
    root.title('Test')
    userInput = InputFromForm(root, dOfValues)
    root.bind('<Return>', (lambda event, e=userInput.temp: userInput.fetch(e)))
    b1 = tk.Button(root, text='OK',command=(lambda e=userInput.temp: [userInput.fetch(e), userInput.close(root)]))
    b1.config(width=25)
    b1.pack(anchor=tk.CENTER, padx=5, pady=20)


    root.mainloop()

if __name__ == '__main__':


    dOfValues = {'Customer No.': '',
            'PO #':'020202',
            'Order Date': '2/3/2012',
            'Zip to code':'92182'}

    #root = tk.Tk()
    #root.title('Test')

    #userInput = InputFromForm(root, dOfValues)

    #root.bind('<Return>', (lambda event, e=userInput.temp: userInput.fetch(e)))
    #b1 = tk.Button(root, text='OK',command=(lambda e=userInput.temp: [userInput.fetch(e), userInput.close(root)]))
    #b1.config(width=25)
    #b1.pack(anchor=tk.CENTER, padx=5, pady=20)


    #root.mainloop()
    extractData(dOfValues)  # Adding this, creates the error. If I put the code 
                            # from this function into main, it works. 

我知道了

【讨论】:

  • @paul 为什么你期望它返回与None不同的东西?
  • @Goyo 因为我从输入字段框中返回用户输入,所以当我调用 fetch() 方法时
  • @paul 我的意思是,这是真的,但你为什么指望extractData 知道或关心它?
  • @Goyo 对不起,我无法关注,你的意思是因为我没有返回任何东西,因此我收到了 None?我的意思是,即使你在 root.mainloop() 之前print(userInput.field),你也会得到一个空列表。我最初拥有的代码返回输入字段中的内容。
  • 问题是当你调用 fetch 时你调用了 close 函数。尝试在 self.field: print(i) before destroy 之前添加类似 for i 的关闭函数。
猜你喜欢
  • 2016-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 2021-10-22
  • 1970-01-01
  • 2021-06-30
  • 2014-07-16
相关资源
最近更新 更多