簡體   English   中英

Tkinter - 如何將實例變量傳遞給另一個類?

[英]Tkinter - How to pass instance variable to another class?

我用谷歌搜索了很多,但沒有用。 上周發布了一個問題,但沒有答案,因為它似乎太長了......

希望新問題更加清晰。

這只是一小部分代碼,如果您運行它,您將能夠重現該問題。 我需要做的基本上是獲取用戶輸入(來自 mainGUI 類的 E1)並將其傳遞給來自 Database 類的 insert() 函數。 嘗試添加條目時出現的錯誤是:

"self.curs.execute("INSERT INTO diary VALUES (?)", (date)) sqlite3.ProgrammingError: 提供的綁定數量不正確。當前語句使用 1,並且提供了 0 個。

我可以毫無問題地從數據庫中讀取。

任何幫助將非常感激。

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 類的實例訪問它。

此外,你的數據庫應該從繼承mainGUI 這不是應該如何使用繼承。

您對數據庫進行了編碼,因此它需要更改 GUI,這是不尋常的。 相反,您的 GUI 應該是唯一可以修改 GUI 的東西,而您的數據庫應該是唯一可以修改數據庫的東西。 當 GUI 需要向數據庫發送信息或從數據庫獲取信息時,它可以調用數據庫上的方法。

所以,第一步是將數據庫對象傳遞給您的mainGUI類(它應該被命名為MainGUI根據PEP8):

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

接下來,在創建 GUI 時傳入數據庫對象:

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

有了它,您現在可以使用數據庫來獲取和獲取數據,並使用 GUI 來顯示數據。

例如,您的 GUI 應該具有“view_all”方法,因為它處理更改視圖。 它應該調用數據庫的“get_all”方法。 通過使用lambda ,您的代碼將變得更易於閱讀、編寫和調試。

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方法, get_all獲取和返回數據:

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

有了上述所有內容,並且在將相同的概念應用於其他方法之后(即: Database類應該只設置或獲取數據),您就有了一個可重用的Database類,它完全獨立於使用它的 GUI。

我注意到的一件事是您沒有將任何textvariable關聯到 Entry 小部件,因此它將空值傳遞給另一個類。 請嘗試將self.EG1 textvariable ,然后將其傳遞給函數。

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM