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

时间:2012-10-19 15:56:06

标签: python python-3.x tkinter 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)

1 个答案:

答案 0 :(得分: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 = db构造函数中执行GUI。这将使您的代码更容易维护,因为您的方法签名将被简化。

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

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