2013-06-11 69 views
5

子を閉じるときに閉じないtkinterの子供Toplevel()ウィンドウをどのように生成するのですか?親と閉じないtkinterトップレベルウィンドウを作成する

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

スレッド のプロセスを独自のtk mainloopで生成することをお勧めしますか?

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

EDIT

私は現在App.__init__()Toplevel()を呼び出さずrootにウィジェットを追加し、いくつかの点で、この機能を使用して新しいウィンドウで起動します

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

物事をこのようにやっている:

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

rootnew_window()は、元のrootとは異なる変数であり、Tk()の別の呼び出しによって取得されます。

これは右のことです。つまり、子ウィンドウは親から独立していて、両方が閉じられた後、Pythonプロセスが終了します。

私の質問は、それが意味をなさないのですか、私はここでひどく間違って何かしていますか?

答えて

1

どのToplevelsが生きているかを追跡する代わりに、センチネル上でweakrefを使用することができます。各Toplevelに渡され、参照に保存されるオブジェクトです。それぞれのToplevelが死んでいる(閉じている)とき、それはそのセンチネルへの参照を削除します。最後にセンチネルへの参照が削除されると、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モジュールを使用することができますが、上記のソリューションよりも消費者のより多くのメモリだろう、とセットアップにプロセス間のいくつかのフォームを、あなたを必要とします別々のプロセスが情報を共有したい場合は、

+0

私は今、 'tk.Tk()'で新しいルートを取得していますが、 'mainloop()'をもう一度呼び出すことはありません - これははるかに簡単ですが、 'Tk()'は同じマスターを返すシングルトンになると思うでしょうが、その上にウィジェットを作成しても最初のウィンドウには影響しないようです。 –

+0

Btwはオリジナルの質問に私の編集を見る - 私はスレッドではないプロセスを意味した。 –

+1

私はあなたの質問をよく理解していません。私が上に示したものよりはるかに簡単な方法です - 単にToplevelsを使用して 'root.withdraw()'を呼び出す - しかしあなたはすべてのToplevelを閉じることができ、プログラムはバックグラウンドで実行されます。あなたはゾンビプロセスをそうした方法で蓄積します。上記のrigmaroleの目的は、最後のToplevelが閉じられたときにプログラムを終了させることです。あなたの質問に答えることができない場合は、あなたのコードを投稿してください。 – unutbu

関連する問題