Destroying a StaticBoxSizer in wxPython

Hi everyone! I’m trying to build an application in Python using wxpython library.

I would like to add and remove widgets dinamically like in the picture

so that i can add and remove how many StaticBoxSizer I want (each one containing Nome/Descrizione/Subject Area/etc).

I got a good result in adding widgets while I can’t get the way to remove the widgets. I’m successfull in destroying every widget in the StaticBoxSizer but I’m not able to destroy the container StaticBoxSizer itself: if I try to add many blocks and then removing one of them, in the onRemoveMaster method something happens and Python crash.

Thanks for helping!!

My code:

import wx import wx.xrc
import wx.aui
class Example(wx.Frame):

def __init__(self, parent, title):
    super(Example, self).__init__(parent, title=title,
        size = wx.Size( 726,624 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL)

    self.InitUI()
    self.Centre()
    self.Show()

def InitUI(self):

    self.number_of_added = 0

    self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

    #Setup MenuBar
    self.m_menubar1 = wx.MenuBar( 0 )
    self.m_menu1 = wx.Menu()
    self.m_menubar1.Append( self.m_menu1, u"MyMenu" )

    self.m_menu2 = wx.Menu()
    self.m_menubar1.Append( self.m_menu2, u"MyMenu" )

    self.SetMenuBar( self.m_menubar1 )

    #Setup Main Container
    MainSizer = wx.BoxSizer( wx.VERTICAL )

    self.ScrolledWindow = wx.ScrolledWindow( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.HSCROLL|wx.VSCROLL )
    self.ScrolledWindow.SetScrollRate( 1, 1 )
    MainVerticalSizer = wx.BoxSizer( wx.VERTICAL )

    self.m_auinotebook1 = wx.aui.AuiNotebook( self.ScrolledWindow, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.aui.AUI_NB_DEFAULT_STYLE )

    #Costruzione Master Sequence Tab
    self.MasterSequenceTab = wx.ScrolledWindow( self.m_auinotebook1, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.HSCROLL|wx.VSCROLL )
    self.MasterSequenceTab.SetScrollRate( 1, 1 )
    self.MasterVSizer = wx.BoxSizer( wx.VERTICAL )

    MasterButtonSizer = wx.BoxSizer( wx.HORIZONTAL )

    self.ButtonAdd = wx.Button( self.MasterSequenceTab, wx.ID_ANY, u"Add", wx.DefaultPosition, wx.DefaultSize, 0 )
    MasterButtonSizer.Add( self.ButtonAdd, 0, wx.ALL, 5 )
    self.ButtonAdd.Bind(wx.EVT_BUTTON, self.onAddMaster)

    self.ButtonRemove = wx.Button( self.MasterSequenceTab, wx.ID_ANY, u"Remove", wx.DefaultPosition, wx.DefaultSize, 0 )
    MasterButtonSizer.Add( self.ButtonRemove, 0, wx.ALL, 5 )
    self.ButtonRemove.Bind(wx.EVT_BUTTON, self.onRemoveMaster)

    self.MasterVSizer.Add( MasterButtonSizer, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5 )

    self.onAddMaster(self)
    self.m_auinotebook1.AddPage( self.MasterSequenceTab, u"Master Sequence", False )

    #Finalizzazione finestre
    MainVerticalSizer.Add( self.m_auinotebook1, 1, wx.EXPAND, 5 )

    self.ScrolledWindow.SetSizer( MainVerticalSizer )
    self.ScrolledWindow.Layout()
    MainVerticalSizer.Fit( self.ScrolledWindow )
    MainSizer.Add( self.ScrolledWindow, 1, wx.EXPAND |wx.ALL, 5 )

    self.SetSizer( MainSizer )
    self.Layout()
    self.Centre( wx.BOTH )

def onAddMaster(self, event):

    self.number_of_added += 1

    self.MastersbSizerAdded = wx.StaticBoxSizer( wx.StaticBox( self.MasterSequenceTab, 100+self.number_of_added, wx.EmptyString ),wx.VERTICAL )

    self.MasterCheckEnableAdded = wx.CheckBox( self.MastersbSizerAdded.GetStaticBox(), 200+self.number_of_added, u"Enable", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.MasterCheckEnableAdded.SetValue(True)
    self.MastersbSizerAdded.Add( self.MasterCheckEnableAdded, 0, wx.ALIGN_RIGHT|wx.ALL, 5 )

    MasterfgSizerAdded = wx.FlexGridSizer( 0, 2, 0, 0 )
    MasterfgSizerAdded.SetFlexibleDirection( wx.BOTH )
    MasterfgSizerAdded.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )

    self.MasterTextNomeAdded = wx.StaticText( self.MastersbSizerAdded.GetStaticBox(), 1000+self.number_of_added, u"Nome", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.MasterTextNomeAdded.Wrap( -1 )
    MasterfgSizerAdded.Add( self.MasterTextNomeAdded, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

    self.MasterCtrlNomeAdded = wx.TextCtrl( self.MastersbSizerAdded.GetStaticBox(), 300+self.number_of_added, wx.EmptyString, wx.DefaultPosition, wx.Size( 566,-1 ), 0 )
    MasterfgSizerAdded.Add( self.MasterCtrlNomeAdded, 0, wx.ALL, 5 )

    self.MasterTextDescrizioneAdded = wx.StaticText( self.MastersbSizerAdded.GetStaticBox(), 1100+self.number_of_added, u"Descrizione ", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.MasterTextDescrizioneAdded.Wrap( -1 )
    MasterfgSizerAdded.Add( self.MasterTextDescrizioneAdded, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

    self.MasterCtrlDescrizione1 = wx.TextCtrl( self.MastersbSizerAdded.GetStaticBox(), 400+self.number_of_added, wx.EmptyString, wx.DefaultPosition, wx.Size( 566,-1 ), 0 )
    MasterfgSizerAdded.Add( self.MasterCtrlDescrizione1, 0, wx.ALL, 5 )

    self.MastersbSizerAdded.Add( MasterfgSizerAdded, 0, wx.ALL, 5 )

    MasterfgSizerAdded2 = wx.FlexGridSizer( 3, 6, 0, 0 )
    MasterfgSizerAdded2.SetFlexibleDirection( wx.BOTH )
    MasterfgSizerAdded2.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )

    self.MasterTextSubjectAdded = wx.StaticText( self.MastersbSizerAdded.GetStaticBox(), 1200+self.number_of_added, u"Subject Area", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.MasterTextSubjectAdded.Wrap( -1 )
    MasterfgSizerAdded2.Add( self.MasterTextSubjectAdded, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

    self.MasterCtrlSubjectAdded = wx.TextCtrl( self.MastersbSizerAdded.GetStaticBox(), 500+self.number_of_added, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
    MasterfgSizerAdded2.Add( self.MasterCtrlSubjectAdded, 0, wx.ALL, 5 )

    self.MasterTextAlimentanteAdded = wx.StaticText( self.MastersbSizerAdded.GetStaticBox(), 1300+self.number_of_added, u" Alimentante", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.MasterTextAlimentanteAdded.Wrap( -1 )
    MasterfgSizerAdded2.Add( self.MasterTextAlimentanteAdded, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

    self.MasterCtrlAlimentanteAdded = wx.TextCtrl( self.MastersbSizerAdded.GetStaticBox(), 600+self.number_of_added, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
    MasterfgSizerAdded2.Add( self.MasterCtrlAlimentanteAdded, 0, wx.ALL, 5 )

    self.MasterTextGroupAdded = wx.StaticText( self.MastersbSizerAdded.GetStaticBox(), 1400+self.number_of_added, u" Num group", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.MasterTextGroupAdded.Wrap( -1 )
    MasterfgSizerAdded2.Add( self.MasterTextGroupAdded, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

    self.MasterCtrlGroupAdded = wx.TextCtrl( self.MastersbSizerAdded.GetStaticBox(), 700+self.number_of_added, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
    MasterfgSizerAdded2.Add( self.MasterCtrlGroupAdded, 0, wx.ALL, 5 )

    self.MasterTextSchedulingAdded = wx.StaticText( self.MastersbSizerAdded.GetStaticBox(), 1500+self.number_of_added, u"Schedulazione", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.MasterTextSchedulingAdded.Wrap( -1 )
    MasterfgSizerAdded2.Add( self.MasterTextSchedulingAdded, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

    MasterCtrlSchedulingChoicesAdded = [ u"G", u"S", u"D", u"Q", u"M", u"BM", u"TM", u"SM", u"A" ]
    self.MasterCtrlSchedulingAdded = wx.Choice( self.MastersbSizerAdded.GetStaticBox(), 800+self.number_of_added, wx.DefaultPosition, wx.DefaultSize, MasterCtrlSchedulingChoicesAdded, 0 )
    self.MasterCtrlSchedulingAdded.SetSelection( 0 )
    MasterfgSizerAdded2.Add( self.MasterCtrlSchedulingAdded, 0, wx.ALL, 5 )

    self.MasterTextValidoAdded = wx.StaticText( self.MastersbSizerAdded.GetStaticBox(), 1600+self.number_of_added, u" Record valido", wx.DefaultPosition, wx.DefaultSize, 0 )
    self.MasterTextValidoAdded.Wrap( -1 )
    MasterfgSizerAdded2.Add( self.MasterTextValidoAdded, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

    MasterCtrlValido1Choices = [ u"Y", u"N" ]
    self.MasterCtrlValidoAdded = wx.Choice( self.MastersbSizerAdded.GetStaticBox(), 900+self.number_of_added, wx.DefaultPosition, wx.DefaultSize, MasterCtrlValido1Choices, 0 )
    self.MasterCtrlValidoAdded.SetSelection( 0 )
    MasterfgSizerAdded2.Add( self.MasterCtrlValidoAdded, 0, wx.ALL, 5 )
    self.MastersbSizerAdded.Add( MasterfgSizerAdded2, 0, wx.ALL, 5 )
    self.MasterVSizer.Add( self.MastersbSizerAdded, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )

    self.MasterSequenceTab.SetSizer( self.MasterVSizer )
    self.MasterSequenceTab.Layout()
    self.MasterVSizer.Fit( self.MasterSequenceTab )

def onRemoveMaster(self, event):

    for i in range(16,0,-1):
        button = 100*i+self.        number_of_added
widget = self.MasterSequenceTab.FindWindowById(button)
        widget.Destroy()

    self.MasterSequenceTab.SetSizer( self.MasterVSizer )
    self.MasterSequenceTab.Layout()
    self.MasterVSizer.Fit( self.MasterSequenceTab )

    self.number_of_added -= 1

if __name__ == '__main__':
app = wx.App()
Example(None, title='Test')
app.MainLoop()

Hi!

I got a good result in adding widgets while I can't get the way to remove the widgets. I'm successfull in destroying every widget in the StaticBoxSizer but I'm not able to destroy the container StaticBoxSizer itself: if I try to add many blocks and then removing one of them, in the onRemoveMaster method something happens and Python crash.

Problems are easier to solve when you attach the code and provide just a minimum sample...

It's certainly possible to add and remove items on the fly.

Your problem is the following:
You add sizers and widgets to your main sizer.
Then you destroy widgets that are in your sizers. The sizer still wants to access its children and crashes.

Switching to Detach does stop the crashes already:

     def onRemoveMaster(self, event):
         self.MasterVSizer.Detach(self.number_of_added-1)
         self.MasterSequenceTab.Layout()
         self.MasterVSizer.Fit( self.MasterSequenceTab )
         self.number_of_added -= 1

But you still need to Destroy the detached items. I'm not sure whether there's a method which would recursively destroy the subsizers and widgets.
Have a look at the wxSizer Class Reference.

Regards,

Dietmar

···

On 24.10.2016 17:40, Ilopan wrote: