簡體   English   中英

Python3.x:tkinter(ttk)停止顯示小部件

[英]Python3.x: tkinter (ttk) stop displaying widget

所以我一直試圖用tkinter制作一些基本的GUI(不要與Tkinter混淆),我遇到了一個問題,我知道沒有解決辦法,也無法在全能的Google上找到任何東西...我有一個我的電腦上有一個目錄表的小型SQLite數據庫。 我想將所有目錄路徑繪制到標簽中,並在該標簽旁邊添加一個“rempve”按鈕。 該按鈕應該能夠從數據庫中刪除目錄,並將其從GUI中刪除。 我還有一個“添加”按鈕,可以在其中添加目錄到數據庫,這個新目錄應該顯示在GUI中。 這是我的基本布局:

---------------
| ADD         |
|dir1   REMOVE|
|dir2   REMOVE|
---------------

我使用gridlayout來顯示按鈕和標簽。 大多數工作都有效,所有與數據庫相關的東 此外,當啟動GUI時,當前目錄和“刪除”按鈕很好地顯示。 但是......當使用“刪除”按鈕時,即使目錄不在數據庫中,目錄也不會從GUI中消失,重新啟動GUI當然會修復它。 添加標簽有效...但我不確定我是否正確地做到了......
我怎么能以某種方式用新信息“重新繪制”GUI? 這是我的GUI代碼:

class GUI():

def __init__(self,db):
    self.root = Tk()
    self.root.title("Example")
    self.frame = ttk.Frame(self.root, padding="3 3 12 12")
    self.frame.rowconfigure(5, weight=1)
    self.frame.columnconfigure(5, weight=1)
    self.frame.grid(sticky=W+E+N+S)

    lbl = ttk.Label(self.frame, text="", width=17)
    lbl.grid(row=0, column=2, sticky=W)
    ttk.Button(self.frame, text="Add directory", command=lambda:self.load_file(db), width=30).grid(row=0, column=0, sticky=W, padx=(500,50))
    ttk.Button(self.frame, text="Sort files", command=lambda:self.sort(db,lbl), width=17).grid(row=0, column=1, sticky=W)
    self.draw(db)
    self.root.mainloop()

def load_file(self,db):
    fname = filedialog.askdirectory()
    db.addPath(fname)
    self.draw(db)

def remove_dir(self,db,pid):
    db.removePath(pid)
    self.draw(db)

def sort(self,db,lbl):
    lbl['text'] = 'Sorting...'
    sortFiles.moveFiles(db)
    lbl['text'] = 'Done!'


def draw(self,db):
    i = 0
    paths = db.getPaths()
    for path in paths:
        ttk.Label(self.frame,text=path[1]).grid(row=1+i,column=0,sticky=W)
        ttk.Button(self.frame, text="Remove directory", command=lambda:self.remove_dir(db,path[0]), width=17).grid(row=1+i,column=1, sticky=E)
        i = i+1
    for child in self.frame.winfo_children(): child.grid_configure(padx=5, pady=5)
    if i == 0:
        ttk.Label(self.root,text='No directories added yet').grid(row=1,column=0,sticky=W)

如果您希望每次添加或刪除某些內容時重繪GUI,則需要先創建舊的小部件,然后再創建新的小部件。 例如:

def draw(self, db):
    # first, delete any existing widgets
    for child in self.frame.winfo_children():
        child.destroy()
    # next, redraw all the widgets
    paths = db.getPaths()
for path in paths:
        ...

你有另一個錯誤,就是你如何使用lambda。 由於它與問題中的代碼一致,所有回調都將看到相同的值。 通過將值指定為lambda的關鍵字參數,您將獲得正確的值:

ttk.Button(..., command=lambda p=path[0]:self.remove_dir(db, p)...)

與實際問題無關,我認為你不需要傳遞db 假設您只使用一個db,我建議您在GUI構造函數中執行self.db = db 這將使您的代碼更容易維護,因為您的方法簽名將被簡化。

最后,當您刪除一個項目時,確實沒有必要完全重繪GUI。 您一次只能刪除一個標簽和按鈕。 這需要您花一點時間考慮如何管理程序中的數據。 例如,如果您保留對每個標簽和按鈕的引用,則可以在從數據庫中刪除路徑時將其刪除。 您的removeDir函數可能類似於:

def removeDir(self, pid):
    label, button = self.widgets(pid)
    label.destroy()
    button.destroy()

暫無
暫無

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

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