Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使tkinter顶层窗口不';不要和父母亲近_Python_Tkinter - Fatal编程技术网

Python 使tkinter顶层窗口不';不要和父母亲近

Python 使tkinter顶层窗口不';不要和父母亲近,python,tkinter,Python,Tkinter,我应该如何在tkinter中生成子Toplevel()窗口,这些窗口在父窗口关闭时不会关闭 我是否需要让家长保留子窗口的“引用计数”,截取WM_DELETE_WINDOW并在所有子窗口都消失后只调用root.destroy() 或者用它自己的tkmainloop生成另一个线程进程是可以接受的做法吗 还是有更优雅的方式 编辑 我现在是这样做的 root = Tk() app = App(root) # doesn't call Toplevel() root.mainloop() 其中App.\

我应该如何在tkinter中生成子
Toplevel()
窗口,这些窗口在父窗口关闭时不会关闭

我是否需要让家长保留子窗口的“引用计数”,截取
WM_DELETE_WINDOW
并在所有子窗口都消失后只调用
root.destroy()

或者用它自己的tk
mainloop
生成另一个线程进程是可以接受的做法吗

还是有更优雅的方式

编辑

我现在是这样做的

root = Tk()
app = App(root) # doesn't call Toplevel()
root.mainloop()
其中
App.\uuuu init\uuuuu()
将小部件添加到
根目录
,而无需调用
Toplevel()
,并且在某些时候生成一个带有此函数的新窗口:

def new_window():
    root = Tk()
    window = App2(root) # doesn't call Toplevel() either
请注意,
new_window()
中的
root
与原始
root
是一个不同的变量,该变量是通过另一次调用
Tk()
获得的

所有这些似乎都做了正确的事情,即子窗口独立于父窗口而存在,python进程在两者都关闭后死亡


所以我的问题变成了,这有意义吗,或者我在这里做了一些可怕的错误吗?

不必跟踪哪些顶层是活动的,您可以在哨兵上使用一个,只是一些传递到每个顶层并保存在引用中的对象。当每个顶级死亡(关闭)时,让它删除对哨兵的引用。删除对sentinel的最后一个引用时,将自动调用weakref回调,
self.no_sentinel
,然后为您调用
root.destroy

import Tkinter as tk
import weakref


class Sentinel(object):
    pass


class Window(tk.Toplevel):
    def __init__(self, master, sentinel, **kwargs):
        title = kwargs.pop('title')
        self.sentinel = sentinel
        tk.Toplevel.__init__(self, master, **kwargs)
        self.protocol("WM_DELETE_WINDOW", self.ondelete)
        self.label = tk.Label(self, text=title)
        self.label.pack(padx=10, pady=10)

    def ondelete(self):
        self.destroy()
        del self.sentinel


class App(object):
    def __init__(self, master, **kwargs):
        self.master = master
        sentinel = Sentinel()
        parent = Window(master, sentinel, title='Parent')
        child = Window(master, sentinel, title='Child')
        self._ref = weakref.ref(sentinel, self.no_sentinel)            
        # When we exit `__init__` only two strong references to sentinal
        # remain -- in parent and child. When both strong references are
        # deleted, `self.no_sentinel` gets called.
    def no_sentinel(self, *args):
        self.master.destroy()

root = tk.Tk()
root.withdraw()
app = App(root)
root.mainloop()

或者,您可以使用
多处理
模块生成另一个进程,以生成另一个Tkinter窗口和mainloop,但这将比上述解决方案占用更多内存,如果希望单独的进程共享信息,则需要设置某种形式的进程间通信。

我现在使用
tk.tk()
获得一个新的根目录,但不再次调用
mainloop()
,这似乎很简单,但可以工作,知道为什么吗?您可能认为
Tk()
将是一个返回相同主窗口的单例,但在其上创建小部件似乎不会影响第一个窗口。顺便说一句,查看我对原始问题的编辑-我的意思是进程而不是线程。我不太确定我是否理解您的问题。有一种比我上面介绍的简单得多的方法——只需使用Toplevels并调用
root.draw()
——但之后可以关闭所有Toplevels,程序仍将在后台运行。这样会累积僵尸进程。上面这个繁琐的操作的目的是使程序在最后一个顶层关闭时结束。如果我没有回答你的问题,请发布你的代码。我不知道你编辑的问题的答案。我知道上面说,“您应该为每个程序只创建一个根小部件”,但如果您多次调用
tk.tk()
(而只调用
root.mainloop
一次),我不知道会出现什么问题(如果有)。