Python 从函数到类内函数的函数调用失败

Python 从函数到类内函数的函数调用失败,python,class,tkinter,Python,Class,Tkinter,我正在尝试设置一个程序,其中tkinter GUI函数位于一个类中,而数据库函数位于另一个类中。我在两个类之外都有一个函数,当我试图调用DB类中的函数时,该函数会失败。你能帮我解决这个错误吗?我的GUI和任何数据库是否都应该处于单独的功能中,或者这是一个糟糕的设计。附加的代码是一个精简版本,以说明我的问题。单击“全部查看”按钮将生成错误 import sqlite3 from tkinter import * from tkinter import messagebox class DB:

我正在尝试设置一个程序,其中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()
````

您需要将
db
传递到
App\u 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)

编辑:忘了删除self。

我想出来了!除了您的更改之外,我还必须从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()

谢谢你的建议,但是现在我得到了以下错误:第25行,在view\u命令rows=db中。view(self)name错误:name“self”没有定义我已经弄明白了!我必须从rows=db.view()中删除“self”。谢谢你的帮助!有人对我最初的问题有任何设计反馈吗?我的GUI和数据库功能应该在不同的类中,还是设计得很差?每个tkinter窗口应该是一个单独的类吗?