Python Tkinter兄弟窗口交互

时间:2014-02-09 04:40:53

标签: python tkinter

我的第一个Python / Tkinter项目是1000行。时间有些指示让我走在路上。 所以我想最初禁用显示布局按钮(灰色)。加载文件后,显示布局处于活动状态。

def ReadFile()
    #Something Magical Happens
    Layoutbutton.config(state='active')

def DisplayLayout()
    #Draw Great gobs of stuff

def main()
    global Layoutbutton
    #setup root window yada yada yada
    Layoutbutton=Button(root,text="Layout",command=DisplayLayout,underline=0)
    Layoutbutton.place(relx=.5,rely=.85,anchor=CENTER)
    root.bind("l",DisplayLayout)
    root.bind('L',DisplayLayout)
    Layoutbutton.config(state='disabled')

    BrowesButton=Button(root,text="File",command=ReadFile,underline=0)
    BrowesButton.place(relx=.75,rely=.85,anchor=CENTER)
    root.bind("F",ReadFile)
    root.bind('f',ReadFile)

if __name__ == '__main__':

    root=Tk()
    main()

这一切都按预期工作。在读取文件之前,将显示DisplayLayout按钮。

我质疑全局LayoutButton的使用。我有很多此类事情正在发生。 如果(没有更好的术语)兄弟窗口如何在没有太多全局变量的情况下相互通信?

2 个答案:

答案 0 :(得分:1)

使函数ReadFile接受参数:

def ReadFile(LayoutButton):
    #Something Magical Happens
    LayoutButton.config(state='active')

main内定义一个用ReadFile调用LayoutButton的函数。用新的功能替换ReadFile的出现。

def main():
    #global Layoutbutton   # No need to declare LayoutButton as global.

    def wrapper(event=None):          # <-------
        return ReadFile(Layoutbutton) # <-------

    #setup root window yada yada yada
    Layoutbutton=Button(root,text="Layout",command=wrapper,underline=0) # <--
    Layoutbutton.place(relx=.5,rely=.85,anchor=CENTER)
    root.bind("l",DisplayLayout)
    root.bind('L',DisplayLayout)
    Layoutbutton.config(state='disabled')

    BrowesButton=Button(root,text="File",command=wrapper,underline=0)   # <--
    BrowesButton.place(relx=.75,rely=.85,anchor=CENTER)
    root.bind("F", wrapper) # <-------
    root.bind('f', wrapper) # <-------

或者,您可以使用lambda代替函数:

wrapper = lambda event=None: ReadFile(Layoutbutton).

或者使用类构建程序。

答案 1 :(得分:0)

你可以通过客观化你的代码来绕过使用全局变量。例如,您的示例的不同实现可能是:

def read_file():
    #magic happens    

class MyFrame(object):
    def __init__(self,parent):
        self.parent = parent
        self.layout_button = Button(self.parent,text="Layout",
                             command=self.display_layout,underline=0)
        self.layout_button.place(relx=.5,rely=.85,anchor=CENTER)
        self.parent.bind("l",self.display_layout)
        self.parent.bind('L',self.display_layout)
        self.layout_button.config(state='disabled')
        self.browes_button=Button(self.parent,text="File",
                                  command=self._call_read_file,underline=0)
        self.browes_button.place(relx=.75,rely=.85,anchor=CENTER)
        self.parent.bind("F",self._call_read_file)
        self.parent.bind('f',self._call_read_file)

    def display_layout(self):
        #populate frame etc. 

    def _call_read_file(self):
        read_file()
        self.layout_button.config(state='active')

def main(root):
    frame = MyFrame(root)
    root.mainloop()

if __name__ == "__main__":
    root = Tk()
    main(root)     

这可能是个人偏好,但我发现GU​​I设计更加直观,与大量使用全局变量的代码相比,更容易追踪不需要的行为。通过这种方法,每个帧都保持对其父帧的引用,实质上是在所有帧需要进行更新时相互访问。一个完整且相当愚蠢的例子可能是:

import Tkinter as tk

class MyOtherFrame(object):
    def __init__(self,parent):
        self.root = parent
        self.enable_button = tk.Button(self.root,text="enable",command=self.enable)
        self.enable_button.pack()
        self.disable_button = tk.Button(self.root,text="disable",command=self.disable)
        self.disable_button.pack()
        self.child_frame = tk.Frame(self.root)
        self.child_frame.pack()
        self.child_frame_obj = MyFrame(self.child_frame)

    def enable(self):
        self.child_frame_obj.button.config(state="active")

    def disable(self):
        self.child_frame_obj.button.config(state="disabled")

class MyFrame(object):
    def __init__(self,parent):
        self.root = parent
        self.button = tk.Button(self.root,text="useless button")
        self.button.pack()

def main():
    root = tk.Tk()
    x = MyOtherFrame(root)

    root.mainloop()

if __name__ == "__main__":
    main()