所以我一直试图用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)
答案 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()