1

所以我一直在尝试用 tkinter 制作一些基本的 GUI(不要与 Tkinter 混淆),我遇到了一个我不知道解决方案并且在全能的谷歌上找不到任何东西的问题......我有一个在我的电脑上带有目录表的小型 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)
4

1 回答 1

4

如果您喜欢在每次添加或删除某些内容时重新绘制 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四处走动。假设您只使用一个数据库,我建议您self.db = dbGUI构造函数中这样做。这将使您的代码更易于维护,因为您的方法签名将被简化。

最后,当您删除一项时,确实不需要完全重绘 GUI。您一次只能删除一个标签和一个按钮。这需要您花更多时间考虑如何管理程序中的数据。例如,如果您保留对每个标签和按钮的引用,则可以在从数据库中删除路径时将其删除。您的removeDir函数可能类似于:

def removeDir(self, pid):
    label, button = self.widgets(pid)
    label.destroy()
    button.destroy()
于 2012-10-19T16:51:20.530 回答