Edit: I leave the question open as it is, since it still remains a good question, and the answer may be useful to others. However, I want to note that I found an actual solution to my problem using a completely different approach with AuiManager ; see below .
I am working on setting up MultiSplitterWindow (having spent a lot of time struggling with SashLayoutWindow ). Unfortunately, when I create a MultiSplitterWindow , I see some unexpected behavior when dragging scraps: sashes can be dragged outside the window containing the layout direction. At the very least, this is a behavior I would like to avoid.
Here is the basic setup (you can confirm the behavior below in wxPython demo by simply replacing leftwin with leftwin , etc., also see the sample application below). Where I have RootPanel/BoxSizer , there is a panel (or Frame , or some type of container that you like) using BoxSizer to which MultiSplitterWindow is added - again, as in the demo.
+--------------------------------+ | RootPanel/BoxSizer | |+------------------------------+| || MultiSplitterWindow || ||+--------++--------++--------+|| ||| Panel1 || Panel2 || Panel3 ||| ||| || || ||| ||+--------++--------++--------+|| |+------------------------------+| +--------------------------------+
When you drag, you can get something like this, where ~ and ! that the panel "exists" there, but is not displayed:
+--------------------------------+ | RootPanel/BoxSizer | |+-------------------------------|~~~~~~~~~~~~~+ || MultiSplitterWindow | ! ||+-----------------++-----------|~~++~~~~~~~~+! ||| Panel1 || Panel2 | !! Panel3 !! ||| || | !! !! ||+-----------------++-----------|~~++~~~~~~~~+! |+-------------------------------|~~~~~~~~~~~~~+ +--------------------------------+
If at this moment you drag the RootPanel so that it is wider than the general set of panels, you will see all the panels again. Similarly, if you drag the width back onto Panel1 , you can access the sash for Panel3 (assuming Panel2 not too wide, of course). Moreover, this is what the Inspection Tool reports about: RootPanel keeps its size, but MultiSplitterWindow goes beyond the size of RootPanel/BoxSizer .
Further inspection using the Inspection tool shows that the width values of the virtual and client values are 0, but the actual size value is negative (by the corresponding number of pixels that it was pulled out of the window) when it is out of range. Again, this is crazy behavior; I can’t imagine why it would ever be necessary for a window to be that way.
Now, if you hold Shift so that the _OnMouse method in MultiSplitterWindow sets up neighbors, this does not happen. So one of my approaches was to simply override this method. This works, but I would prefer to override methods this way if absolutely necessary. Is there any other, better way to solve this problem? It does not seem like this would be the expected or desirable behavior in general, so I assume there is a standard way to fix it.
Other things I've tried:
- Check if the sum of the values in the
MultiWindowSplitter width of the containing window using each of the EVT_SPLITTER_SASH_POS_CHANGED and EVT_SPLITTER_SASH_POS_CHANGING events, and then try to fix the problem:- Using the call to
event.Veto() - Using the
SetSashPosition() Method on a Separator
- Overriding the
_OnMouse() method to use the behavior that is usually associated with holding the Shift . It works, but it ends up giving me other results that I don't like. - Setting minimum panel sizes using the
SetMinimumPaneSize method - Setting maximum size on
MultiSplitterWindow via SetMaxSize() - Setting the maximum size on
RootPanel/BoxSizer using SetMaxSize() and SetSizeHints() on RootPanel .- I even did this with an event handler for
wx.EVT_SIZE in the container, so the RootPanel always has the corresponding maximum size from the parent of the frame - I tried using the same event handling method for
MultiSplitterWindow , which also has no effect.
Version Information
I have confirmed that this is displayed on 32-bit and 64-bit versions of Windows, from the latest wxPython snapshot assembly, for both Python 2.7 and 3.3.
Working example (with the inspection tool enabled)
The following is essentially a duplicate (and a little simplified) of the demo source. This is a working demonstration of the problem.
import wx, wx.adv import wx.lib.mixins.inspection as wit from wx.lib.splitter import MultiSplitterWindow class AppWInspection(wx.App, wit.InspectionMixin): def OnInit(self): self.Init() # enable Inspection tool return True class MultiSplitterFrame(wx.Frame): def __init__(self, *args, **kwargs): super().__init__(size=(800, 800), *args, **kwargs) self.SetMinSize((600, 600)) self.top_sizer = wx.BoxSizer(orient=wx.HORIZONTAL) self.SetSizer(self.top_sizer) self.splitter = MultiSplitterWindow(parent=self, style=wx.SP_LIVE_UPDATE) self.top_sizer.Add(self.splitter, wx.SizerFlags().Expand().Proportion(1).Border(wx.ALL, 10)) inner_panel1 = wx.Panel(parent=self.splitter) inner_panel1.SetBackgroundColour('#999980') inner_panel1_text = wx.StaticText(inner_panel1, -1, 'Inner Panel 1') inner_panel1.SetMinSize((100, -1)) inner_panel2 = wx.Panel(parent=self.splitter) inner_panel2.SetBackgroundColour('#999990') inner_panel2_text = wx.StaticText(inner_panel2, -1, 'Inner Panel 2') inner_panel2.SetMinSize((100, -1)) inner_panel2.SetMaxSize((100, -1)) inner_panel3 = wx.Panel(parent=self.splitter) inner_panel3.SetBackgroundColour('#9999A0') inner_panel3_text = wx.StaticText(inner_panel3, -1, 'Inner Panel 3') inner_panel3.SetMinSize((100, -1)) self.splitter.AppendWindow(inner_panel1) self.splitter.AppendWindow(inner_panel2) self.splitter.AppendWindow(inner_panel3) if __name__ == '__main__': app = AppWInspection(0) frame = MultiSplitterFrame(parent=None, title='MultiSplitterFrame Test') app.SetTopWindow(frame) frame.Show() app.MainLoop()