2016-09-20 3 views
0

現在、2つのウィンドウを持つwxWigetsでPythonアプリケーションを作成しています。最初のものはメインの「コントローラ」ウィンドウで、もう1つはデータ表示ウィンドウです。wxPython + weakref proxy =閉じるwx.Frameは返されません。

私は、最初のウィンドウがすでに生成されていた場所を知るためのメカニズムを用意したいと思います。私はPythonのweakref.proxy()を使用していますが、言語の理解が少ないため、オブジェクトがクローズ/破棄/割り当て解除された場合には、プロキシを呼び出すときにNoneの値が返され、これはPythonのis None/is not None演算子で便利にチェックできます。

ウィンドウが一度生成される限り、プロキシは意図したとおりに動作し、ウィンドウがまだ生成されていない場合はNoneを返し、それ以外の場合はオブジェクトへの参照を返します。しかし、二次ウィンドウを閉じるとすぐに、プロキシオブジェクトはNoneに戻らず、私のアプリケーションはReferenceError: weakly-referenced object no longer existsでクラッシュします。私は以前この問題を解決しようとすると、私が見つけたほとんどの機能ソリューションは以下のように、内部WXクラスに対してオブジェクトのクラス名をチェックしていた覚え

if windowObject.__class__.__name__ is not "_wxPyDeadObject": #do stuff 

これは、しかし、と非常にハック解決策のように思えます私は、上記以外のよりよい方法があるかどうかを知りたいと思います。以下は私のこの問題を再現するいくつかの基本的なコードです。 WXウィジェットオブジェクトはPythonのプロキシオブジェクトのクラスを破壊してきたこれまで見てきたように

import wx 
import weakref 


class SillyWindow(wx.Frame): 
    def __init__(self): 
     wx.Frame.__init__(self, parent=None, title="Spawned Window") 
     self.Show() 


class ExWindow(wx.Frame): 
    def __init__(self): 
     wx.Frame.__init__(self, parent=None, title="Main Window") 

     self.panel = wx.Panel(self) 
     self.button = wx.Button(self.panel, label="Spawn window!") 
     self.Bind(wx.EVT_BUTTON, self.spawn, self.button) 
     self.txt = wx.TextCtrl(self.panel, pos=(0,100)) 

     self.wind = None 

     self.timer = wx.Timer(self) 
     self.Bind(wx.EVT_TIMER, self.update, self.timer) 
     self.timer.Start(50) 
     self.Show() 

    def spawn(self,event): 
     if self.wind is None: # Preventing multiple spawning windows 
      self.wind = weakref.proxy(SillyWindow()) 

    def update(self,event): 
     if self.wind is not None: 
      self.txt.SetValue(str(self.wind)) 
     else: 
      self.txt.SetValue("None") 


app = wx.App(False) 
frame = ExWindow() 
app.MainLoop() 

答えて

2

は、あなたがそれを使用しようとすると、例外を発生させるためにそれを変更するものと交換されています。また、あなたはそれがクラスの名前です見つけるために、代わりにオブジェクトの根性を掘り下げるのこのようなことを行うことができますので、__nonzero__方法があります。

if not windowObject: 
    # it has been destroyed already 
    return 

心に留めておくべきもう一つは、トップレベルウィンドウが破壊されていないということです彼らが閉じられたとき、またはそのDestroyメソッドが呼び出されたとき。代わりに、保留中のイベントがなくなるとすぐに処理される保留中の削除リストに追加されます。フレームのIsBeingDeletedメソッドを呼び出すことによって、そのケース(クローズされていますが、まだ破棄されていない)をテストできます。また、UIオブジェクトのC++部分もPythonオブジェクトへの参照を保持していますが、C++オブジェクトが破棄されたときにはそのオブジェクトが参照されます。だから、これらの事のいくつかまたはすべてがあなたのweafrefのアプローチに干渉している可能性があります。個人的には、私は上記のようなifステートメントを使用します。ショート。甘い。シンプル。

P.S.私がここで言及した詳細のいくつかはwxPython Classicに固有であり、Phoenixでも同じように扱われません。しかし、上記のような文を使用してもifは動作します。

+0

パーフェクト; 'もしそうでなければwindowObject'は私が探していた優雅な解決策の一種です! – MVittiS

関連する問題