Defining a wx.Panel destructor in wxpython
Question:
Answers:
You should be able to bind to EVT_WINDOW_DESTROY and do the unsub in the handler.
For example:
class MyPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, wx.NewId())
pub.subscribe(self.__handler, 'event')
def __destroy(_):
pub.unsubscribe(self.__handler, 'event')
self.Bind(wx.EVT_WINDOW_DESTROY, __destroy)
If above is not working you can protect against the PyDeadObjectError exception, by adding the following in the code where you try to access ExtendedWxPanel:
if instanceOfExctendedWxPanel:
then access it or methods of it.
I had the same issue, I solved it by doing the following:
My code (which gave the error) was:
import wx
from pubsub import pub
class My_panel(wx.panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.box = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.box)
#
pub.subscribe(self.do_something, 'Msg')
def do_something(self):
self.box.Layout()
The above panel was in a wx.Notebook page. In my app the user has the possibility to add or delete page from this notebook.
When the pub.sendMessage(‘Msg’) code line was run after that the user deleted the notebook page containing this panel, I had the following error:
RuntimeError: wrapped C/C++ object of type BoxSizer has been deleted
which seems to be ~~ the new error type of ‘wx.PyDeadObjectError exception’ according to wxPython: https://wxpython.org/Phoenix/docs/html/MigrationGuide.html
What is explained in such documentation from wxPython is to use the nonzero() method which tests if the C++ object has been deleted.
Hence my working code is:
import wx
from pubsub import pub
class My_panel(wx.panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.box = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.box)
#
pub.subscribe(self.do_something, 'Msg')
def do_something(self):
if self.__nonzero__():
self.box.Layout()
You should be able to bind to EVT_WINDOW_DESTROY and do the unsub in the handler.
For example:
class MyPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, wx.NewId())
pub.subscribe(self.__handler, 'event')
def __destroy(_):
pub.unsubscribe(self.__handler, 'event')
self.Bind(wx.EVT_WINDOW_DESTROY, __destroy)
If above is not working you can protect against the PyDeadObjectError exception, by adding the following in the code where you try to access ExtendedWxPanel:
if instanceOfExctendedWxPanel:
then access it or methods of it.
I had the same issue, I solved it by doing the following:
My code (which gave the error) was:
import wx
from pubsub import pub
class My_panel(wx.panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.box = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.box)
#
pub.subscribe(self.do_something, 'Msg')
def do_something(self):
self.box.Layout()
The above panel was in a wx.Notebook page. In my app the user has the possibility to add or delete page from this notebook.
When the pub.sendMessage(‘Msg’) code line was run after that the user deleted the notebook page containing this panel, I had the following error:
RuntimeError: wrapped C/C++ object of type BoxSizer has been deleted
which seems to be ~~ the new error type of ‘wx.PyDeadObjectError exception’ according to wxPython: https://wxpython.org/Phoenix/docs/html/MigrationGuide.html
What is explained in such documentation from wxPython is to use the nonzero() method which tests if the C++ object has been deleted.
Hence my working code is:
import wx
from pubsub import pub
class My_panel(wx.panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.box = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.box)
#
pub.subscribe(self.do_something, 'Msg')
def do_something(self):
if self.__nonzero__():
self.box.Layout()