Tkinter摧毁顶层窗户也会破坏其他窗户

时间:2015-08-09 22:47:31

标签: python python-2.7 tkinter

我在使用Toplevel窗口遇到这种非常奇怪的行为,我有这样的逻辑:

Did user click 'properties button?'
    yes? bind <ButtonPress-1> to window that will call properties(mouselocation)

properties(mouselocation):
    find location of cursor
    create property window at cursor

我遇到的问题是,不知何故,当我创建多个窗口并尝试关闭一个窗口时,它们全部关闭。我设法创建了一个突出我的问题的最小例子,PropertiesDialog类正是我正在使用的减去几个小的更改,所以它可以用于这个例子:

from Tkinter import *

class PropertyDialog(Toplevel):
    def __init__(self, root, string):
        Toplevel.__init__(self)
        self.wm_overrideredirect(1)
        self.\
             geometry('+%d+%d' %
                      (root.winfo_pointerx(),
                       root.winfo_pointery()))
        try:
            self.tk.call('::Tk::unsupported::MacWindowStyle',
                                         'style', self._w,
                                         'help', 'noActivates')
        except TclError:
            pass
        window_frame = Frame(self)
        window_frame.pack(side=TOP, fill=BOTH, expand=True)
        exit_frame = Frame(window_frame, background='#ffffe0')
        exit_frame.pack(side=TOP, fill=X, expand=True)
        button = Button(exit_frame, text='x', width=3, command=self.free,
               background='#ffffe0', highlightthickness=0, relief=FLAT)
        button.pack(side=RIGHT)
        text_frame = Frame(window_frame)
        text_frame.pack(side=TOP, fill=BOTH, expand=True)
        label = Label(text_frame, text=string, justify=LEFT,
                      background='#ffffe0',
                      font=('tahoma', '8', 'normal'))
        label.pack(ipadx=1)

    def free(self):
        self.destroy()

def bind():
    """
    toggle property window creation mode
    """
    root.bind('<ButtonPress-1>', create)


def create(event):
    """
    Create actual window upon mouse click
    """
    t = PropertyDialog(root, 'help me')
    return

root = Tk()
root.geometry('%dx%d' % (300,400))

Button(root, text='create', command=bind).pack()

root.mainloop()

现在,如果您运行此应用程序,请单击create并单击窗口的随机区域,然后尝试关闭一个。出于一个原因,每个窗口在试图销毁一个窗口时关闭。创建这种行为我做错了什么?

1 个答案:

答案 0 :(得分:2)

其他窗户没有被销毁,它们只是被主窗口隐藏起来。如果您创建一些弹出窗口,关闭其中一个弹出窗口,然后移动主窗口,则可以看到它们。

要解决此问题,请将主窗口降低到所有其他窗口的下方。更改的区域标有#CHANGED#

from Tkinter import *

class PropertyDialog(Toplevel):
    def __init__(self, root, string):
        Toplevel.__init__(self)
        self.wm_overrideredirect(1)
        self.root = root #CHANGED# save a reference to the root
        self.\
             geometry('+%d+%d' %
                      (root.winfo_pointerx(),
                       root.winfo_pointery()))
        try:
            self.tk.call('::Tk::unsupported::MacWindowStyle',
                                         'style', self._w,
                                         'help', 'noActivates')
        except TclError:
            pass
        window_frame = Frame(self)
        window_frame.pack(side=TOP, fill=BOTH, expand=True)
        exit_frame = Frame(window_frame, background='#ffffe0')
        exit_frame.pack(side=TOP, fill=X, expand=True)
        button = Button(exit_frame, text='x', width=3, command=self.free,
               background='#ffffe0', highlightthickness=0, relief=FLAT)
        button.pack(side=RIGHT)
        text_frame = Frame(window_frame)
        text_frame.pack(side=TOP, fill=BOTH, expand=True)
        label = Label(text_frame, text=string, justify=LEFT,
                      background='#ffffe0',
                      font=('tahoma', '8', 'normal'))
        label.pack(ipadx=1)

    def free(self): #CHANGED# this method significantly
        self.destroy() # first we destroy this one
        for val,widget in enumerate(dialogs): # go through the dialogs list
            if widget is self: # when we find this widget
                dialogs.pop(val) # pop it out
                break # and stop searching
        if dialogs: # if there are any dialogs left:
            for widget in dialogs: # go through each widget
                widget.lift(aboveThis=self.root) # and lift it above the root

def bind():
    """
    toggle property window creation mode
    """
    root.bind('<ButtonPress-1>', create)


def create(event): #CHANGED# this to store the widget in a list
    """
    Create actual window upon mouse click
    """
    dialogs.append(PropertyDialog(root, 'help me'))

root = Tk()
dialogs = [] #CHANGED# to initialize a list
root.geometry('%dx%d' % (300,400))

Button(root, text='create', command=bind).pack()

root.mainloop()