2016-09-20 3 views
0

현재 두 개의 창이있는 wxWigets로 파이썬 응용 프로그램을 만들고 있습니다. 첫 번째 창은 주 "컨트롤러"창이고, 두 번째 창은 데이터 표시 창입니다.wxPython + weakref proxy = closing wx.Frame does not yield.

두 번째 창이 이미 스폰 된 곳을 알 수있는 첫 번째 창에 대한 메커니즘을 갖고 싶습니다. 그렇다면 사용자가 닫은 경우이를 알 수 있습니다. 나는 파이썬의 weakref.proxy()를 사용했지만, 언어에 대한 나의 작은 이해를 바탕으로, 객체가 닫히거나 파괴되거나/GC가 할당되면, 프록시를 호출하려는 어떤 시도도 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 

이를, 그러나에 매우 hackish 솔루션처럼 보인다 나, 위의 것보다 더 좋은 방법이 있는지 알고 싶습니다. 다음은이 문제를 재현하는 몇 가지 기본 코드입니다. WX 위젯 객체는 파이썬 프록시 객체의 클래스를 파괴되었습니다 당신이 본 것처럼

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. 여기서 언급 한 일부 세부 사항은 wxPython Classic에만 해당되며 Phoenix에서도 동일하게 처리되지 않습니다. 그러나 위와 같은 문을 사용하면 if이 여전히 작동합니다.

+0

Perfect; '그렇지 않다면 windowObject'는 제가 찾고 있던 우아한 솔루션의 종류입니다! – MVittiS