AUI Unexpected Behavior

When converting from a notebook to a AuiNotebook I’ve encountered a couple of unexpected behaviors.
When the program is executed the notebook is appearing in a slice, 18px wide but full panel height. I can resized and dock it on any of the 4 sides. I assumed that this was because the notebook didn’t have a dedicated sizer. However any attempt thus far produces the “already in a sizer, detach first” error. I therefore assumed that AuiNotebook does the sizing. Can anyone verify this?
Here’s a snippet covering the setup.

def __init__(self, parent):
        super().__init__(parent)
        
        self.tabOne_closed = False  # Flag to track tabOne visibility
        
        wx.lib.inspection.InspectionTool().Show()

        # Create AuiManager
        self.mgr = wx.aui.AuiManager(self)
        
        # notebook = wx.Notebook(self, wx.ID_ANY)
        ledger = wx.aui.AuiNotebook(self,
                                    wx.ID_ANY,
                                    style=wx.aui.AUI_NB_DEFAULT_STYLE,
                                    # size=(wx.Size),
                                    # style=wx.aui.AUI_NB_TAB_FIXED_WIDTH
                                    # style=wx.aui.AUI_NB_TOP
                                    )
        
        # ledger.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onPageChanged)

        # Create a panel named "tabOne".
        tabOne = wx.Panel(ledger)
        
        # Add the Panel "tabOne" as a page in the auiNotebook with a tab lable "Ledger".
        ledger.AddPage(tabOne, 'Ledger') 
        
        # Create a vertical BoxSizer to manage the layout of the widgets within 
        # the Panel "tabOne".
        tabOne_sizer = wx.BoxSizer(wx.VERTICAL)
        
        tabOne.SetBackgroundColour((71, 106, 115)) # Greenish

        # Add tabOne to AuiManager
        pane_info = (
            wx.aui.AuiPaneInfo()
            .Name("Notebook")
            .Caption("Ledger")
            # .Gripper()
            # .CenterPane() # using this expands but locks Ledger
            .Resizable()
            # .Top()
            # .PaneBorder()
            .Floatable()
            .Dockable()
        )

        self.mgr.AddPane(ledger, pane_info)

        # Set the AuiManager to manage the layout
        self.mgr.Update()

well, going by the example in the demo they have a horizontal sizer governing the AuiNotebook but, as you assumed, not for each page within :slightly_smiling_face:

You might be using AuiManager for other reasons in your real application but, if you are just creating an AuiNotebook, it’s not necessary.

Example:

import wx
import wx.aui

class TestFrame(wx.Frame):

    def __init__(self, parent):
        super().__init__(parent)

        sizer = wx.BoxSizer(wx.VERTICAL)
        ledger = wx.aui.AuiNotebook(self)
        sizer.Add(ledger, 1, wx.EXPAND, 0)

        # Create a panel named "tabOne".
        tabOne = wx.Panel(ledger)
        tabOne.SetBackgroundColour((71, 106, 115))  # Greenish

        # Add the Panel "tabOne" as a page in the
        # auiNotebook with a tab label "Ledger".
        ledger.AddPage(tabOne, 'Ledger')

        self.SetSizer(sizer)

if __name__ == '__main__':

    app = wx.App()
    frame = TestFrame(None)
    frame.Show()
    app.MainLoop()

I’ve just spent some time experimenting with your original code that uses both AuiManager and AuiNotebook and I’m getting the same results that you did.

If I use .Center() or .CenterPane() dock position, the notebook does expand to fill the space available, but I then can’t drag it to a different dock position. If I use any other dock position (or don’t specify one) then it doesn’t expand to fill the space available.

Yes, that was I found too. So I’m left wondering how far off base I am. I mean am I anywhere close to the correct implementation of the AuiMananger and AuiNotebook? Love the demo and its obvious to me there are plenty of use cases. Even as a boiler plate starting point for an app. I’m again at a point were I’m spending far to much time on the layout and not “actual” coding. If there are any other user groups, resources, books, YouTube video that you can suggest I would be in your debt.

I’ve not found any useful resources for using AuiManager with AuiNotebook.

I did wonder if the pure python version in wx.lib.agw.aui would work better.

There are some examples of this in the bottom half of The "Book" Controls of wxPython (Part 2 of 2) - Mouse Vs Python Note: that document is now quite old and certainly pre-dates Phoenix.

I modified the test script (see below) to use it and I added a second pane containing a ListCtrl so I could test dragging either of them around.

I found that if I set .Center() [but not .CenterPane()] for the notebook, it did expand and I could drag it to a different dock position.

If I drag one of the panes to the bottom of frame, the AGW version displays indicators to show the dock positions. It also overlays a coloured rectangle when the pane is in a position where it can be dropped. However, the version that comes with wxPython 4.2.1 has some bugs and sometimes it draws the coloured rectangle way outside the frame!

The version on the wxPython master branch in GitHub contains a number of bug fixes, so I downloaded it from https://github.com/wxWidgets/Phoenix/blob/a207b4070058c74440bfccc7dc5de0a5a8e8cabe/wx/lib/agw/aui/framemanager.py. I then renamed the original framemanager.py file in the wxPython installation on my linux PC and copied the downloaded file in its place.

However, even the downloaded version still occasionally draws the coloured rectangles outside the frame. Also, after dragging the notebook and listctrl panes around a few times, I have found them to have become ‘merged’ together somehow, after which I can’t drag either of them!

Example using agw.aui

import wx
import wx.lib.agw.aui as aui
import wx.lib
import wx.lib.inspection


class TestFrame(wx.Frame):

    def __init__(self, parent):
        super().__init__(parent)

        # self.tabOne_closed = False  # Flag to track tabOne visibility
        # wx.lib.inspection.InspectionTool().Show()

        # Create AuiManager
        self.mgr = aui.AuiManager(self)

        # notebook = wx.Notebook(self, wx.ID_ANY)
        ledger = aui.AuiNotebook(self,
                                 wx.ID_ANY,
                                 style=aui.AUI_NB_DEFAULT_STYLE,
                                 # size=(wx.Size),
                                 # style=aui.AUI_NB_TAB_FIXED_WIDTH
                                 # style=aui.AUI_NB_TOP
                                 )

        # ledger.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onPageChanged)

        # Create a panel named "tabOne".
        tabOne = wx.Panel(ledger)

        # Add the Panel "tabOne" as a page in the auiNotebook with a tab lable "Ledger".
        ledger.AddPage(tabOne, 'Ledger')

        # tabTwo = wx.TextCtrl(ledger, wx.ID_ANY, "Some text here...",
        #                      style=wx.TE_MULTILINE)
        # ledger.AddPage(tabTwo, 'Text')

        # Create a vertical BoxSizer to manage the layout of the widgets within
        # the Panel "tabOne".
        # tabOne_sizer = wx.BoxSizer(wx.VERTICAL)

        tabOne.SetBackgroundColour((71, 106, 115))  # Greenish

        # Add Notebook to AuiManager
        pane_info = (
            aui.AuiPaneInfo()
            .Center()
            # .Name("Notebook")
            .Caption("Ledger")
            # .Gripper()
            # .CenterPane() # using this expands but locks Ledger
            .Dockable()
            .Resizable()
            # .Top()
            # .PaneBorder()
            .Floatable()
        )

        self.mgr.AddPane(ledger, pane_info)

        lc = wx.ListCtrl(self, wx.ID_ANY, style=wx.LC_REPORT)
        lc.InsertColumn(0, "Name")
        lc.InsertColumn(1, "Quantity")
        pane_info = (aui.AuiPaneInfo()
                     .Caption("ListCtrl")
                     .Bottom()
                     .Dockable()
                     .Resizable())
        self.mgr.AddPane(lc, pane_info)

        # Set the AuiManager to manage the layout
        self.mgr.Update()


if __name__ == '__main__':

    app = wx.App()
    frame = TestFrame(None)
    frame.Show()
    app.MainLoop()

well, from the dogs :cowboy_hat_face:

import wx
from wx import aui

Text = 'Hello'

class NoteBook(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        nb = wx.Notebook(self)
        page = wx.TextCtrl(nb, -1, Text, style=wx.TE_MULTILINE)
        nb.AddPage(page, "Welcome")

        for num in range(1, 5):
            page = wx.TextCtrl(nb, -1, "This is page %d" % num ,
                               style=wx.TE_MULTILINE)
            nb.AddPage(page, "Tab Number %d" % num)

        sizer = wx.BoxSizer()
        sizer.Add(nb, 1, wx.EXPAND)
        self.SetSizer(sizer)
        wx.CallAfter(nb.SendSizeEvent)

class Frame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.mgr = aui.AuiManager()
        self.mgr.SetManagedWindow(self)

        p0 = NoteBook(self)
        p1 = wx.Panel(self, size=(100,100))
        p2 = wx.Panel(self, size=(100,100))

        self.mgr.AddPane(p0, aui.AuiPaneInfo().CenterPane().
            Resizable().Floatable().Dockable())
        self.mgr.AddPane(p1, aui.AuiPaneInfo().Float().
            Caption("p1").Dockable())
        self.mgr.AddPane(p2, aui.AuiPaneInfo().Float().
            Caption("p2").Dockable())
        self.mgr.Update()

app = wx.App()
Frame(None).Show()
app.MainLoop()

Thanks for this. I tried to compare your code to mine and don’t see anything obvious. When I add .CenterPane() to the AddPane method the AuiNotebook appears in the full width and height of the panel. However its not undockable. Does this Widget Inspection screen shot reveal anything?

I’m suspicious that I may be missing a sizer, either I have to add one or ones interfering. I layout of the panel I’m displaying is complex and needs to stay all together. It works fine except for the fact that when the program starts the panel is a an 18px sliver on the left side of the frame.

        tabOne = wx.Panel(self)
        ledger.AddPage(tabOne, 'Ledger') 
        
        tabOne_sizer = wx.BoxSizer(wx.VERTICAL)
        self.mgr.AddPane(ledger,
                         aui.AuiPaneInfo()
                         # .CenterPane()
                         # .Caption("Ledger")
                         .Resizable()
                         .Dockable()
                         .Dock()
                         # .Floatable()
        )
        self.mgr.Update()

        search_sizer = wx.BoxSizer(wx.HORIZONTAL)
        tabOne_sizer.Add(search_sizer, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 10) 

        search_label = wx.StaticText(tabOne, label="Budget Item:")
        font = wx.Font(11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL,
                       wx.FONTWEIGHT_NORMAL)
        search_label.SetFont(font)
        search_label.SetForegroundColour(wx.WHITE)  # Set the text color to white
        search_sizer.Add(search_label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
        
        search_sizer.Add(search_label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
        
        budget_items = budget_items_combobox()
        self.budgetItemSelected = wx.ComboBox(tabOne,
                                              value=budget_items[1] 
                                              if budget_items else "",
                                              choices=budget_items)
        
        self.budgetItemSelected.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
        search_sizer.Add(self.budgetItemSelected, 2, wx.ALL, 5)

        self.search_ctrl.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)

        search_label = wx.StaticText(tabOne, label="Player Account:")
        font = wx.Font(11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL,
                       wx.FONTWEIGHT_NORMAL)
        search_label.SetFont(font)
        search_label.SetForegroundColour(wx.WHITE)  # Set the text color to white
        search_sizer.Add(search_label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)

        playerAccounts = playerAccount_items_combobox()
        self.playerAccountSelected = wx.ComboBox(tabOne,
                                              value=playerAccounts[1] 
                                              if playerAccounts else "",
                                              choices=playerAccounts)

        playerAccountWidth = 125
        self.playerAccountSelected.SetMinSize((playerAccountWidth, -1))
        
        search_sizer.Add(self.playerAccountSelected, 2, wx.ALL, 5)
        
        self.playerAccountSelected.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)

        search_label = wx.StaticText(tabOne, label="Payment Method:")
        font = wx.Font(11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL,
                       wx.FONTWEIGHT_NORMAL)
        search_label.SetFont(font)
        search_label.SetForegroundColour(wx.WHITE)  # Set the text color to white
        search_sizer.Add(search_label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
        
        paymentMethod = [
            "eTransfer",
            "Cheque",
            "Credit Card",
            "All"]
        
        self.paymentMethod = wx.ComboBox(tabOne, value="All",
                              choices=paymentMethod)
        paymentMethodWidth = 125
        self.paymentMethod.SetMinSize((paymentMethodWidth, -1))
        search_sizer.Add(self.paymentMethod, 2, wx.ALL, 5)
        self.paymentMethod.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)

        search_btn = wx.Button(tabOne, label="Search")
        search_sizer.Add(search_btn, 0, wx.ALL, 5)
        search_btn.Bind(wx.EVT_BUTTON, self.OnSearch)
        search_sizer.AddStretchSpacer(12)  # Add a flexible space to push elements to the right
        
        credit_label = wx.StaticText(tabOne, label="Credit:")
        credit_label_font = wx.Font(11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
        credit_label.SetFont(credit_label_font)
        credit_label.SetForegroundColour(wx.WHITE)  # Set the text color to white
        search_sizer.Add(credit_label, 0, 5)
        
        self.credit_text = wx.TextCtrl(tabOne, style=wx.NO_BORDER)  # Create a TextCtrl instance with initial value
        self.credit_text.SetBackgroundColour(wx.Colour(71, 106, 115))
        self.credit_text.SetForegroundColour(wx.Colour(255, 255, 255))
        credit_text_font = wx.Font(11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)
        self.credit_text.SetFont(credit_text_font)
        self.credit_text.SetMaxSize((-1, -1))  # Set minimum width for credit text box                                             
        self.credit_text.SetValue("0.00")
        search_sizer.Add(self.credit_text, 0, wx.ALL | wx.CENTER, 5)

        debit_label = wx.StaticText(tabOne, label="Debit:")
        debit_label_font = wx.Font(11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
        debit_label.SetFont(debit_label_font)
        debit_label.SetForegroundColour(wx.WHITE)  # Set the text color to white
        search_sizer.Add(debit_label, 0, 5)
       
        self.debit_text = wx.TextCtrl(tabOne, style=wx.NO_BORDER)   # Create a TextCtrl instance with initial value
        self.debit_text.SetMaxSize((-1, -1))  # Set minimum width for debit text box
        self.debit_text.SetBackgroundColour(wx.Colour(71, 106, 115))
        self.debit_text.SetForegroundColour(wx.Colour(255, 255, 255))  # Set the text color to white
        debit_text_font = wx.Font(11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)
        self.debit_text.SetFont(debit_text_font)
        self.debit_text.SetValue("0.00")
        search_sizer.Add(self.debit_text, 0, wx.ALL | wx.CENTER, 5)

        balance_label = wx.StaticText(tabOne, label="Balance:")
        balance_label_font = wx.Font(11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
        balance_label.SetFont(balance_label_font)
        balance_label.SetForegroundColour(wx.Colour(255, 255, 255))
        balance_label.SetBackgroundColour(wx.Colour(71, 106, 115))
        search_sizer.Add(balance_label, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5)
        
        self.balance_text = wx.TextCtrl(tabOne, style=wx.NO_BORDER)  # Create a TextCtrl instance with initial value
        balance_text_font = wx.Font(11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)
        self.balance_text.SetFont(balance_text_font)
        self.balance_text.SetMaxSize((-1, -1))  # Set minimum width for balance text box
        self.balance_text.SetForegroundColour(wx.Colour(255, 255, 255))
        self.balance_text.SetBackgroundColour(wx.Colour(71, 106, 115))
        self.balance_text.SetValue("0.00")
        search_sizer.Add(self.balance_text, 0, wx.ALIGN_CENTER_VERTICAL, 1)
        search_sizer.AddStretchSpacer(1)  # Add another flexible space to push the elements to the far right
        
      font = wx.Font(11, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
        self.ledger_results_olv.SetFont(font)   

        # Add the results to the sizer
        tabOne_sizer.Add(self.ledger_results_olv, 1, wx.ALL | wx.EXPAND, 1)

        # Create button sizer and add it to tabOne.
        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
        tabOne_sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5)
        
        # Set row colors
        self.ledger_results_olv.evenRowsBackColor = wx.Colour(230, 230, 230)
        self.ledger_results_olv.oddRowsBackColor = wx.Colour(250, 250, 250)
        
        # Add Record Button
        add_record_btn = wx.Button(tabOne, label="Add")
        # add_record_btn.SetBackgroundColour((29, 38, 89))
        add_record_btn.Bind(wx.EVT_BUTTON, self.add_record)
        btn_sizer.Add(add_record_btn, 0, wx.ALL, 5)
    
        # Edit Record Button
        edit_record_btn = wx.Button(tabOne, label="Edit")
        edit_record_btn.Bind(wx.EVT_BUTTON, self.edit_record)
        btn_sizer.Add(edit_record_btn, 0, wx.ALL, 5)
    
        # Delete Button
        delete_record_btn = wx.Button(tabOne, label="Delete")
        delete_record_btn.Bind(wx.EVT_BUTTON, self.OnDeleteRecord)
        btn_sizer.Add(delete_record_btn, 0, wx.ALL, 5)
    
        # Show All Button
        show_all_btn = wx.Button(tabOne, label="Show All")
        show_all_btn.Bind(wx.EVT_BUTTON, self.OnShowAll)
        btn_sizer.Add(show_all_btn, 0, wx.ALL, 5)
    
        tabOne.SetSizer(tabOne_sizer)
        # self.SetSizer(panel_sizer)
        self.Layout()
        self.Centre()

I think that what you are seeing is intentional.

My theory is that the AuiManager bases its calculations for the sizes of the panes on the expectation that one of them is specified as CenterPane.

Looking in the wxWidgets 3.2.2.1 source code at file src/aui/framemanager.cpp I noticed in the wxAuiManager::LayoutAll() method, there is a comment which states:

// there are no center docks, add a background area

I think that it is this background area which prevents notebook in your example from taking up the space itself.

I think the reason that a CenterPane can’t be dragged is that, if it were moved to a different dock position, there would no longer be a center pane and the AuiManager wouldn’t be able to calculate the sizes of the other panes correctly.

It’s possible to specify more than one pane as CenterPane() and hide all but one of them. The AUI_DockingWindowMgr example in the wxPython Demo shows how this can work. It has options in its View menu for switching which of the center panes is currently shown.

Just wanted to get out a quick thank you. Your response gives me some hope that a work around is possible. I’ll think about work around using your theory. Thanks so much.

well, the only work around here is a non existing concept :rofl:

import wx
from wx import aui

Text = 'Hello'

class NoteBook(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        nb = wx.Notebook(self)
        page = wx.TextCtrl(nb, -1, Text, style=wx.TE_MULTILINE)
        nb.AddPage(page, "Welcome")

        for num in range(1, 5):
            page = wx.TextCtrl(nb, -1, "This is page %d" % num ,
                               style=wx.TE_MULTILINE)
            nb.AddPage(page, "Tab Number %d" % num)

        sizer = wx.BoxSizer()
        sizer.Add(nb, 1, wx.EXPAND)
        sizer.SetMinSize(parent.GetSize())
        self.SetSizerAndFit(sizer)
        wx.CallAfter(nb.SendSizeEvent)

class Frame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.mgr = aui.AuiManager()
        self.mgr.SetManagedWindow(self)

        p0 = NoteBook(self)
        p1 = wx.Panel(self, size=(100,100))
        p2 = wx.Panel(self, size=(100,100))

        self.mgr.AddPane(p0, aui.AuiPaneInfo().Float().Dockable())
        self.mgr.AddPane(p1, aui.AuiPaneInfo().Float().
            Caption("p1").Dockable())
        self.mgr.AddPane(p2, aui.AuiPaneInfo().Float().
            Caption("p2").Dockable())
        self.mgr.Update()

app = wx.App()
Frame(None).Show()
app.MainLoop()

I have done numerous more experiments than posted fellow wxeroknights, but…

… to tell you truthfully…

… DONT TRUST ROBINBOT! …

… plus this short dab of code …
“”“import this”""
Put that into Guido’s grand interpreter and bite down hard. :slight_smile: It’s how we know you are real here.

well, the size of the panes at drop time is governed by DockSizeConstraint of the manager, but I think the 1/3 default is a good choice :sunglasses:

what does drop time mean? 1/3 is the default, that’s not what I’m seeing. I’m seeing 1/10 of the width and 100% of the height. I called self.mgr.SetDockSizeConstraint(50, 50) with no impact.

No idea what this reply has to do within the context of the thread. Please explain.

1 Like

and in case you lost sight of some panes (close doesn’t destroy unless specified) :sweat_smile:

import wx
from wx import aui
# from wx.lib.agw import aui

class NoteBook(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        # nb = wx.Notebook(self)
        nb = aui.AuiNotebook(self)
        page = wx.TextCtrl(nb, -1, 'Hello', style=wx.TE_MULTILINE)
        nb.AddPage(page, "Welcome")

        for num in range(1, 5):
            page = wx.TextCtrl(nb, -1, "This is page %d" % num ,
                               style=wx.TE_MULTILINE)
            nb.AddPage(page, "Tab Number %d" % num)

        vbox = wx.BoxSizer()
        vbox.Add(nb, 1, wx.EXPAND)
        vbox.SetMinSize(parent.GetSize())
        self.SetSizerAndFit(vbox)
        wx.CallAfter(nb.SendSizeEvent)

class Frame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        mb = wx.MenuBar()
        help_menu = wx.Menu()
        ID_About = wx.NewIdRef()
        help_menu.Append(ID_About, "restore pains...")
        mb.Append(help_menu, "Help")
        def menu_about(e):
            for entry in self.mgr.GetAllPanes():
                if not entry.IsShown():
                    entry.Show()
                self.mgr.Update()
        self.Bind(wx.EVT_MENU, menu_about, id=ID_About)
        self.SetMenuBar(mb)

        self.mgr = aui.AuiManager()
        self.mgr.SetManagedWindow(self)
        # self.mgr.SetDockSizeConstraint(0.5, 0.5)
        print(f'{self.mgr.GetDockSizeConstraint()=}')
        self.mgr.Bind(aui.EVT_AUI_PANE_CLOSE,
                    lambda evt: print(f'on close: {evt.GetPane().caption=})'))

        p0 = NoteBook(self)
        p1 = wx.Panel(self, size=(100,100), name='panel 1')
        p2 = wx.Panel(self, size=(100,100))
        p1.Bind(wx.EVT_WINDOW_DESTROY,
                    lambda evt: print(evt.GetWindow().GetName()))

        # self.mgr.AddPane(p0, aui.AuiPaneInfo().Float().
            # Caption('book').Dockable())
        s = self.GetSize()
        self.mgr.AddPane(p0, aui.AuiPaneInfo().Floatable().
            Caption('book').MinSize(s - (int(s[0]/2), 0)).Dock())
        self.mgr.AddPane(p1, aui.AuiPaneInfo().Float().
            Caption("p1").Dockable())
        self.mgr.AddPane(p2, aui.AuiPaneInfo().Float().
            Caption("p2").Dockable())
        self.mgr.Update()

app = wx.App()
Frame(None).Show()
app.MainLoop()

I sometimes feel the same way… If I have to reply from an email or reply by someone else, I oftentimes am left without context.

Sorry if what I may be posting may not be relevant now, but, in reality AUI is undergoing a lot of changes, and unless the python side can keep up with their changes makes it exceptionally harder to track code change “type” dynamically since the buildbot has apparently been broken for everything but apple/Mac builds at the moment.

This makes it almost impossible for me to help anyone here if I have to deal with a bot annoying me that someone MIGHT have relevant nothing details about a custom subject only I or modded users should even know about.

I can still argue with you about a RELz version but without the buildbot, you have to depend on MY time, which, might take months, or… at worst a “never” sort/type of answer.

wxAUI and wxpyAUI right now is at a major dividing point from what you have known. Beware any changes anywhere since 4.0.7post2 in a program jump because of underlying wxWidgets changes.

Basically I’m telling you hold on to your custom python version if you have one, else sacrifice it to the new guesswork to try and keep up the pace.