tkinter,"刷新"主窗口

时间:2015-11-08 14:25:00

标签: python tkinter

虽然我认为解决方案可能类似于这个问题:tkinter, display a value from subwindow in mainwindow,我仍然决定提出这个问题,因为我很难自己解决这个问题。

我有列表"字段"我正在创建任何给定数量的行,其中有两个实验室。在打开一个子窗口后,我希望能够操作该列表(在我的示例中只是简单地追加)并且在单击按钮(此处" ADD")之后,我希望主窗口更新,这样它就显示了被操纵列表的行。它在大多数情况下工作正常,但我不知道在这个例子中更新主窗口的最佳方法是什么。

我能想出的唯一解决方案是破坏主窗口并重新创建它,但我觉得这可能不是最好的解决方案。还有更好的吗?

import tkinter as tk

a=0
fields=[("a",1),("c",2),("e",3)]

class clsApp(object):

    def __init__(self):
        self.root=tk.Tk()
        self.root.title("MainWindow")
        ##Labels##
        self.rootLabel=tk.Label(self.root, text="WindowAppExperiment", padx=100)
        self.aLabel=tk.Label(self.root, text=a, padx=100)
        ##Buttons##
        self.BtExit=tk.Button(self.root, text="Quit", fg="red", command=self.root.quit)
        ###self.BtNewWindow=tk.Button(self.root, text ="Edit", command=lambda:self.clsNewWindow(self.root, self.aLabel).run())
        self.BtNewField=tk.Button(self.root, text ="New Field", padx=30, command=lambda:self.clsNewFields(self.root).run())

    def grid (self):
        self.rootLabel.pack()
        self.aLabel.pack()
        self.fckPackFields()
        self.BtNewField.pack()
        self.BtExit.pack(side="left")
        ###self.BtNewWindow.pack(side="right")

    def fckPackFields(self):
        if fields:
            for field in fields:
                ##create labels##
                row=tk.Frame(self.root)
                nameLabel=tk.Label(row, text =field[0], width=20, anchor="w")
                valueLabel=tk.Label(row, text =field[1], width=5)
                ##pack labels##
                row.pack(side="top", fill="x", padx=5, pady=5)
                nameLabel.pack(side="left")
                valueLabel.pack(side="right", expand=True, fill="x")


    def run(self):
        self.grid()
        self.root.mainloop()
        self.root.destroy()

    class clsNewFields(object):

        def __init__(self, Parent):
            self.parent=Parent
            ##Window##
            self.top=tk.Toplevel()
            self.top.title("Add Fields")
            ##Labels##
            self.enterNameLabel=tk.Label(self.top, text ="Enter fieldname", padx=10)
            self.enterValueLabel=tk.Label(self.top, text ="Enter value", padx=10)
            ##Entryfields##
            self.EntryName=tk.Entry(self.top)
            self.EntryValue=tk.Entry(self.top)
            ##Buttons##
            self.BtADD=tk.Button(self.top, text ="ADD", command=lambda:self.fckAddField(self.EntryName, self.EntryValue))
            self.BtClose=tk.Button(self.top, text ="Close", command=self.top. quit)

        def grid(self):
            self.enterNameLabel.pack()
            self.enterValueLabel.pack()
            self.EntryName.pack()
            self.EntryValue.pack()
            self.BtADD.pack()
            self.BtClose.pack()

        def fckAddField(self, Name, Value):
            self.name=Name.get()
            self.value=Value.get()
            global fields
            fields.append((self.name, self.value))
            print(fields)
            self.parent.update


        def run(self):
            self.grid()
            self.top.mainloop()
            self.top.destroy()



clsApp().run()

1 个答案:

答案 0 :(得分:0)

欢迎使用StackOverflow。

首先 - 你真的想宣布你的clsNewFields内的clsApp 吗?是的,应该在App中使用Fields,但我认为不需要使用 class-in-class-declaration

第二 - 您正在def fckPackFields(self):中打包字段。更新时不会自动调用它。

您未使用update调用self.parent.update功能。

您正在使用字段的全局变量,这不适合您的需求。为什么不在App类中列出如下列表:

    def __init__(self):
        self.__fields=[]
    def __set_fields(self, value):
        self.__fields=value
    def __get_fields(self):
        return self.__fields
    Fields = property(__get_fields, __set_fields)

    def __loadUI(self, event=None):
        # This function should be called at the end of __init__
        self.fieldFrame=tk.Frame(self.root)
        self.fieldFrame.pack(side="top")

    def fckPackFields(self):
        #First clean area
        [...]
        #Then add fields
        for field in self.__fields:
            # create the row, etc.
            # !!! but do it inside self.fieldFrame !!!
            [...]

我更喜欢在这里使用网格而不是打包,因为在那里我认为将框架放置在某个位置更容易,然后你可以销毁self.fieldFrame并在同一位置重新创建它以放置其中的字段。

<强>更新

再次检查您的代码。通过一些简单的技巧,您可以调整GUI以执行您想要的操作:

    def __init__(self):    
        self.fieldFrame=None   #this line has been added

    #completely reworked this function
    def grid(self):
        self.rootLabel.grid(row=1, column=0, columnspan=2, sticky=tk.NW+tk.SE)
        self.fckPackFields()
        self.BtNewField.grid(row=3, column=0, sticky=tk.NW+tk.SE)
        self.BtExit.grid(row=3, column=1, sticky=tk.NW+tk.SE)

    #Only one line changed / one added
    def fckPackFields(self):
        self.__cleanFields()    #added this line, function beyond
        if fields:
            for field in fields:
                ##create labels##
                row=tk.Frame(self.fieldFrame)    #add the row to the fieldFrame
                [...]
    #In here we destroy and recreate fieldFrame as needed
    def __cleanFields(self):
        if self.fieldFrame: 
                self.fieldFrame.destroy()
        ##FieldFrame##
        self.fieldFrame=tk.Frame(self.root)
        self.fieldFrame.grid(row=2, column=0, columnspan=2)

clsNewFields


    def fckAddField(self, Name, Value):
        [...]
        self.parent.fckPackFields() # instead of self.parent.update

修改

看看这两个问题:

我并不是要指出一般要避免使用嵌套类,但我确实希望将您的注意力集中在的思想上“对于我的用例来说,它是否真的有必要或有益”< / em>的