【问题标题】:function call from a function to a function within a class fails从函数到类中的函数的函数调用失败
【发布时间】:2020-04-06 15:41:43
【问题描述】:

我正在尝试设置一个程序,其中我的 tkinter GUI 函数在一个类中,而我的数据库函数在另一个类中。当我尝试调用 DB 类中的函数时,我有两个类外部的函数失败。你能帮我解决这个错误吗?我的 GUI 和任何数据库是否应该在单独的功能中,或者是一个糟糕的设计。附加的代码是一个精简的版本来说明我的问题。单击“查看全部”按钮会产生错误。

import sqlite3
from tkinter import *
from tkinter import messagebox

class DB:
    def __init__(self):
        self.conn = sqlite3.connect("mybooks.db")
        self.cur = self.conn.cursor()
        self.cur.execute(
            "CREATE TABLE IF NOT EXISTS book (id INTEGER PRIMARY KEY, title TEXT, author TEXT, isbn INTEGER)")
        self.conn.commit()

    def __del__(self):
        self.conn.close()

    def view(self):
        self.cur.execute("SELECT * FROM book")
        rows = cur.fetchall()
        return rows

def view_command():
    # there is a problem with the next line
    # when rows=DB.view() error is TypeError: view() missing 1 required positional argument: 'self'
    # when rows=DB.view(self) error is NameError: name 'self' is not defined
    rows=DB.view(self)
    for row in rows:
        print(row)

class App_GUI():   # create the main window
    def __init__(self, master):                         
        self.master = master
        self.master.title("My Books")       

        self.master.l1 = Label(self.master, text="Title")
        self.master.l1.grid(row=0, column=0)

        self.master.l2 = Label(self.master, text="Author")
        self.master.l2.grid(row=0, column=2)

        self.master.l3 = Label(self.master, text="ISBN")
        self.master.l3.grid(row=1, column=0)

        self.master.title_text = StringVar()
        self.master.e1 = Entry(self.master, textvariable=self.master.title_text)
        self.master.e1.grid(row=0, column=1)

        self.master.author_text = StringVar()
        self.master.e2 = Entry(self.master, textvariable=self.master.author_text)
        self.master.e2.grid(row=0, column=3)

        self.master.isbn_text = StringVar()
        self.master.e3 = Entry(self.master, textvariable=self.master.isbn_text)
        self.master.e3.grid(row=1, column=1)

        self.master.list1 = Listbox(self.master, height=6, width=35)
        self.master.list1.grid(row=2, column=0, rowspan=6, columnspan=2)

        self.master.sb1 = Scrollbar(self.master)
        self.master.sb1.grid(row=2, column=2, rowspan=6)

        self.master.list1.configure(yscrollcommand=self.master.sb1.set)
        self.master.sb1.configure(command=self.master.list1.yview)

        self.master.b1 = Button(self.master, text="View all", width=12, command=view_command)
        self.master.b1.grid(row=2, column=3)

        self.master.b6 = Button(self.master, text="Close", width=12, command=self.master.destroy)
        self.master.b6.grid(row=7, column=3)
        return

###############################
# Program Main                #
###############################
def main():
    db = DB()
    root = Tk()         
    def on_closing():
        dd = db
        if messagebox.askokcancel("Quit", "Do you want to close the application"): # ask the user if he/she wants to close the application
            root.destroy()
            del dd
    root.protocol("WM_DELETE_WINDOW", on_closing) # catch the user closing the window
    app = App_GUI(root)                     # creation of an instance
    root.mainloop()                         # tkinter mainloop

if __name__ == '__main__':
    main()
````

【问题讨论】:

    标签: python class tkinter


    【解决方案1】:

    您需要将db 传递给App_GUI,然后再传递给函数:

    
    def view_command(db):
        rows = db.view()
        for row in rows:
            print(row)
    
    class App_GUI():   # create the main window
        def __init__(self, master, db):  
            # other stuff elided ...
            self.master.b1 = Button(self.master, text="View all", width=12, command=lambda : view_command(db))
    
    ...
    def main():
        db = DB()
        # other stuff elided
        app = App_GUI(root, db)
    

    编辑:忘记删除自己。

    【讨论】:

    • 感谢您的建议,但现在我收到以下错误:第 25 行,在 view_command rows=db.view(self) NameError: name 'self' is not defined
    • 我想通了!我不得不从 rows=db.view() 中删除“self”。感谢您的帮助!
    • 有人对我最初的问题有任何设计反馈吗?我的 GUI 和数据库功能是否应该在不同的类中,或者这是一个糟糕的设计?每个 tkinter 窗口应该是一个单独的类吗?
    【解决方案2】:

    我想通了!除了您的更改之外,我还必须从 rows=db.view() 中删除“self”。谢谢你的帮助!修改后的代码:

    import sqlite3
    from tkinter import *
    from tkinter import messagebox
    
    class DB:
        def __init__(self):
            self.conn = sqlite3.connect("mybooks.db")
            self.cur = self.conn.cursor()
            self.cur.execute(
                "CREATE TABLE IF NOT EXISTS book (id INTEGER PRIMARY KEY, title TEXT, author TEXT, isbn INTEGER)")
            self.conn.commit()
    
        def __del__(self):
            self.conn.close()
    
        def view(self):
            self.cur.execute("SELECT * FROM book")
            rows = self.cur.fetchall()
            return rows
    
    def view_command(db):
        rows=db.view()
        for row in rows:
            print(row)
    
    class App_GUI():   # create the main window
        def __init__(self, master, db):                         
            self.master = master
            self.master.title("My Books")       
    
            self.master.l1 = Label(self.master, text="Title")
            self.master.l1.grid(row=0, column=0)
    
            self.master.l2 = Label(self.master, text="Author")
            self.master.l2.grid(row=0, column=2)
    
            self.master.l3 = Label(self.master, text="ISBN")
            self.master.l3.grid(row=1, column=0)
    
            self.master.title_text = StringVar()
            self.master.e1 = Entry(self.master, textvariable=self.master.title_text)
            self.master.e1.grid(row=0, column=1)
    
            self.master.author_text = StringVar()
            self.master.e2 = Entry(self.master, textvariable=self.master.author_text)
            self.master.e2.grid(row=0, column=3)
    
            self.master.isbn_text = StringVar()
            self.master.e3 = Entry(self.master, textvariable=self.master.isbn_text)
            self.master.e3.grid(row=1, column=1)
    
            self.master.list1 = Listbox(self.master, height=6, width=35)
            self.master.list1.grid(row=2, column=0, rowspan=6, columnspan=2)
    
            self.master.sb1 = Scrollbar(self.master)
            self.master.sb1.grid(row=2, column=2, rowspan=6)
    
            self.master.list1.configure(yscrollcommand=self.master.sb1.set)
            self.master.sb1.configure(command=self.master.list1.yview)
    
            self.master.b1 = Button(self.master, text="View all", width=12, command=lambda : view_command(db))
            self.master.b1.grid(row=2, column=3)
    
            self.master.b6 = Button(self.master, text="Close", width=12, command=self.master.destroy)
            self.master.b6.grid(row=7, column=3)
            return
    
    ###############################
    # Program Main                #
    ###############################
    def main():
        db = DB()
        root = Tk()         
        def on_closing():
            dd = db
            if messagebox.askokcancel("Quit", "Do you want to close the application"): # ask the user if he/she wants to close the application
                root.destroy()
                del dd
        root.protocol("WM_DELETE_WINDOW", on_closing) # catch the user closing the window
        app = App_GUI(root, db)                     # creation of an instance
        root.mainloop()                         # tkinter mainloop
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-27
      相关资源
      最近更新 更多