【问题标题】:Python3.x: tkinter (ttk) stop displaying widgetPython3.x:tkinter (ttk) 停止显示小部件
【发布时间】:2012-10-19 15:56:06
【问题描述】:

所以我一直在尝试用 tkinter 制作一些基本的 GUI(不要与 Tkinter 混淆),我遇到了一个我不知道解决方案并且在全能的 Google 上找不到任何东西的问题...... 我的电脑上有一个带有目录表的小型 SQLite 数据库。我想将所有目录路径绘制到一个标签中,并在该标签旁边添加一个“rempve”按钮。该按钮应该能够从数据库中删除目录,也可以从 GUI 中删除它。我还有一个“添加”按钮,可以在其中向数据库添加目录,这个新目录应该显示在 GUI 中。这是我的基本布局:

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

我使用网格布局来显示按钮和标签。大多数事情都有效,所有与数据库相关的东西都有效。此外,当启动 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)

【问题讨论】:

    标签: python python-3.x tkinter widget


    【解决方案1】:

    如果您希望在每次添加或删除某些内容时重绘 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。假设您只使用单个数据库,我建议您在 GUI 构造函数中执行 self.db = db。这将使您的代码更易于维护,因为您的方法签名将被简化。

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

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

    【讨论】:

    • 你的回答实际上解决了我所有的问题......我试图只破坏按钮和标签(在跟踪后工作),但它在 GUI 中产生了奇怪的结果。例如:当有 2 个目录并删除顶部的一个时,两个标签都显示相同的目录。然后删除最上面的标签后,标签将与开始时的内容相反(即使目录已从数据库中删除并且所有引用都已删除)。重新绘制整个 GUI(这是备份计划)效果很好,尽管我仍然对如何在不重新绘制所有内容的情况下做到这一点感到好奇。
    猜你喜欢
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    相关资源
    最近更新 更多