Tkinter - 如何将实例变量传递给另一个类? [英] Tkinter - How to pass instance variable to another class?

查看:28
本文介绍了Tkinter - 如何将实例变量传递给另一个类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用谷歌搜索了很多,但没有奏效.上周发布了一个问题但没有答案,因为它似乎太长了......

I googled a lot but it didn't work. Posted a question last week but no answer as it seems that it was too lengthily...

希望新问题更清楚.

这只是一小段代码,如果您运行它,您将能够重现该问题.我需要做的基本上是获取用户输入(来自 mainGUI 类的 E1)并将其传递给来自 Database 类的 insert() 函数.尝试添加条目时出现的错误是:

This is just a small piece of the code and if you run it you will be able to reproduce the issue. What I need to do basically is to get user input (E1 from mainGUI class) and pass it to insert() function from Database class. The error I get when I try to add an entry is:

"self.curs.execute("INSERT INTO diary VALUES (?)", (date))sqlite3.ProgrammingError:提供的绑定数量不正确.当前语句使用 1,并且提供了 0."

"self.curs.execute("INSERT INTO diary VALUES (?)", (date)) sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 0 supplied."

我可以毫无问题地从数据库中读取数据.

I can read from the database with no problems.

任何帮助将不胜感激.

from tkinter import *
import sqlite3

    class mainGUI(object):

    def __init__(self,window):

        self.window=window 

        self.E1 = Entry(window)                           
        self.E1.grid(row=1, column=0)
        self.EG1 = self.E1.get()

        global E4
        E4 = Listbox(window)                           
        E4.grid(row=2)

        B1 = Button(window, text="Add entry", command=lambda: database.insert(self.EG1)) 

        B1.grid(row=1, column=4)

        B2 = Button(window, text="View all", command=database.view_all)  
        B2.grid(row=2, column=4, sticky="WN")

        window.mainloop()

class Database(mainGUI):

    def __init__(self, db):
        self.conn = sqlite3.connect(db)
        self.curs = self.conn.cursor() 
        self.curs.execute("CREATE TABLE IF NOT EXISTS diary (date TEXT)")   
        self.conn.commit()

    def insert(self,date): 
        database.add_entry(date) 
        E4.delete(0, END)
        E4.insert(END,(date))

    def add_entry(self,date):     
        self.curs.execute("INSERT INTO diary VALUES (?)", (date))
        self.conn.commit()

    def view_all(self): 
        E4.delete(0, END)    
        self.curs.execute("SELECT * FROM diary")
        data = self.curs.fetchall()
        for row in data:
           E4.insert(END,row)                           

if __name__ == "__main__":   
    database = Database("dbase.db")
    window=Tk()
    gui = mainGUI(window)

推荐答案

如果您正在使用类,则不应使用全局变量.相反,您需要访问对象实例的属性和方法.这意味着创建 E4 作为实例变量,并通过 GUI 类的实例访问它.

If you are using classes, you should not be using global variables. Instead, you need to be accessing attributes and methods of your object instances. That means creating E4 as an instance variable, and access it via the instance of the GUI class.

此外,您的数据库不应继承自mainGUI.这不是应该如何使用继承.

Also, your Database should not inherit from mainGUI. That is not how inheritance should be used.

您的数据库已编码,因此需要更改 GUI,这是不寻常的.相反,您的 GUI 应该是唯一可以修改 GUI 的东西,而您的数据库应该是唯一可以修改数据库的东西.当GUI需要向数据库发送信息或从数据库获取信息时,它可以调用数据库上的方法.

You have your Database coded so that it need to alter the GUI, which is unusual. Instead, your GUI should be the only thing that can modify the GUI, and your Database should be the only thing that modifies the database. When the GUI needs to send information to, or get information from the database, it can call methods on the database.

因此,第一步是将数据库对象传递给您的 mainGUI 类(根据 PEP8 应命名为 MainGUI):

So, the first step is to pass the database object to your mainGUI class (which should be named MainGUI according to PEP8):

class MainGUI(object):
    def __init__(self,window, db):
        self.window = window
        self.db = db
        ...

接下来,在创建 GUI 时传入数据库对象:

Next, pass in the database object when you create the GUI:

if __name__ == "__main__":   
    database = Database("dbase.db")
    window=Tk()
    gui = MainGUI(window, database)

这样,您现在可以使用数据库来获取和获取数据,并使用 GUI 来显示数据.

With that, you can now use the database to get and fetch data, and use the GUI to display the data.

例如,您的 GUI 应该具有view_all"方法,因为它处理更改视图.它应该调用数据库的get_all"方法.通过使用lambda,您的代码将变得更易于阅读、编写和调试.

For example, your GUI should have the "view_all" method, since it deals with altering the view. It should call the "get_all" method of the database. By not using lambda, your code becomes much easier to read, write, and debug.

class mainGUI(object):
    def __init__(self,window, db):
        ...
        self.E4 = Listbox(...)
        ...
        B2 = Button(..., command=self.view_all) 

    def view_all(self):
        data = self.db.get_all()
        self.E4.delete(0, END)    
        for row in data:
           self.E4.insert(END,row)

最后,在您的 Database 中创建一个 get_all 方法,它只获取和返回数据:

Finally, create a get_all method in your Database that does nothing but get and return the data:

class MainGUI(object):
    def get_all(self):   
        self.curs.execute("SELECT * FROM diary")
        data = self.curs.fetchall()
        return data

有了以上所有内容,并且在将相同的概念应用于其他方法之后(即:Database 类应该只设置或获取数据),您就有了一个可重用的 Database 类完全独立于使用它的 GUI.

With all of the above, and after applying the same concepts to the other methods (ie: the Database class should only set or get data), you have a reusable Database class that is completely independent of the GUI that uses it.

这篇关于Tkinter - 如何将实例变量传递给另一个类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆