5

Toplevel()親が閉じたときに閉じないtkinterの子ウィンドウをどのように生成すればよいですか?

親に子ウィンドウの「参照カウント」を保持させ、インターセプトして、すべての子がなくなったときにWM_DELETE_WINDOWのみ呼び出す必要がありますか?root.destroy()

それとも、独自の tk を使用して別のスレッドプロセスを生成することは許容されるのmainloopでしょうか?

それとももっとエレガントな方法がありますか?

編集

私は現在、この方法で物事を行っています

root = Tk()
app = App(root) # doesn't call Toplevel()
root.mainloop()

whereはを呼び出さずApp.__init__()に にウィジェットを追加し、ある時点でこの関数を使用して新しいウィンドウを生成します。rootToplevel()

def new_window():
    root = Tk()
    window = App2(root) # doesn't call Toplevel() either

rootinnew_window()は元の とは異なる変数であり、 へのroot別の呼び出しによって取得されることに注意してくださいTk()

これはすべて、正しいことをしているように見えます。つまり、子ウィンドウは親から独立して存在し、両方が閉じられた後、python プロセスは終了します。

それで私の質問は、それは理にかなっていますか、それとも私はここでひどく間違ったことをしていますか?

4

1 に答える 1

1

どのトップレベルが生きているかを追跡する代わりに、各トップレベルに渡され、参照に保存されるいくつかのオブジェクトだけをセンチネルでweakrefを使用できます。各トップレベルが終了する (閉じられる) と、センチネルへの参照が削除されます。センチネルへの最後の参照が削除されると、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 ウィンドウとメインループを作成することもできますが、上記のソリューションよりも多くのメモリを消費することになり、別のプロセスで情報を共有する場合は、何らかの形式のプロセス間通信をセットアップする必要がありますmultiprocessing .

于 2013-06-11T12:54:40.053 に答える