python - Constrain wxPython MultiSplitterWindow panes -


edit: i'm leaving question open is, it's still question , answer may useful others. however, i'll note found actual solution my issue using different approach auimanager; see answer below.

i'm working on multisplitterwindow setup (after spending deal of time struggling against sashlayoutwindow layout quirks). unfortunately, when create multisplitterwindow, see unexpected behavior when dragging sashes around: sashes can dragged outside containing window in direction of layout. least, behavior i'd avoid.

here basic setup (you can confirm behavior below in wxpython demo, substituting leftwin panel1, etc., see below example app). have rootpanel/boxsizer, there panel (or frame, or whatever kind of container element like) boxsizer multisplitterwindow added – again, in demo.

+--------------------------------+ |       rootpanel/boxsizer       | |+------------------------------+| ||     multisplitterwindow      || ||+--------++--------++--------+|| ||| panel1 || panel2 || panel3 ||| |||        ||        ||        ||| ||+--------++--------++--------+|| |+------------------------------+| +--------------------------------+ 

when drag, can end this, ~ , ! indicate panel "exists" there isn't being displayed:

+--------------------------------+ |       rootpanel/boxsizer       | |+-------------------------------|~~~~~~~~~~~~~+ ||           multisplitterwindow |             ! ||+-----------------++-----------|~~++~~~~~~~~+! |||      panel1     ||   panel2  |  !! panel3 !! |||                 ||           |  !!        !! ||+-----------------++-----------|~~++~~~~~~~~+! |+-------------------------------|~~~~~~~~~~~~~+ +--------------------------------+ 

if @ point, drag rootpanel wider overall set of panels, see panels again. likewise, if drag width down on panel1, can access sash panel3 again (assuming panel2 isn't wide, of course). moreover, precisely situation reported inspection tool: rootpanel retains size, multisplitterwindow grows beyond size of rootpanel/boxsizer.

further examination inspection tool reveals virtual , client width values both 0, actual size value negative (by corresponding number of pixels dragged out of window) whenever it's out of range. again, nutty behavior; can't imagine why 1 ever want window behave way.

now, if 1 holds down shift _onmouse method in multisplitterwindow adjusts neighbors, doesn't happen. thus, 1 of approaches override method. works, i'd prefer override methods way if absolutely necessary. there another, better way solve problem? doesn't seem expected or desirable behavior in general, imagine there standard way of fixing it.

other things i've tried:

  • checking whether sum of values in multiwindowsplitter exceeds width of containing window, using each of evt_splitter_sash_pos_changed , evt_splitter_sash_pos_changing events, , trying fix issue by:
    • using event.veto() call
    • using setsashposition() method on splitter
  • overriding _onmouse() method use behavior associated holding down shift key. works, ends giving me other results don't like.
  • setting minimum pane sizes via setminimumpanesize method
  • setting maximum size on multisplitterwindow via setmaxsize()
  • setting maximum size on rootpanel/boxsizer using both setmaxsize() , setsizehints() on rootpanel.
    • i've done event handler wx.evt_size on container rootpanel always has appropriate maximum size parent frame element
    • i've attempted same event handling approach multisplitterwindow, no effect.

version info

i have confirmed appears in windows 32-bit , os x 64-bit, latest snapshot build of wxpython, against both python 2.7 , 3.3.

working example (with inspection tool included)

the following duplicates (and simplifies) demo source. it's working demonstration of problem.

import wx, wx.adv import wx.lib.mixins.inspection wit 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() 

depending on 1 needs for, 1 possible option use instead of custom-managed multisplitterwindow (or sashlayoutwindow combinations, etc.) advanced user interface kit's auimanager tool (documentation pre-phoenix version here; phoenix docs here). auimanager automates lot of these kinds of things you. in case, attempting use multisplitterwindow way of controlling collapsible , resizable panels ui in question, auimanager perfect fit: has controls , constraints need built in.

in case, 1 needs create auimanager instance

(i'm leaving here an answer in hopes others may taking same naive approach taking find useful, not selecting answer because not directly answer original question.)

sample use of aui under phoenix

this code sample trying multisplitterwindow, managed automatically auimanager.

import wx, wx.adv import wx.lib.mixins.inspection wit wx.lib.agw import aui   class appwinspection(wx.app, wit.inspectionmixin):     def oninit(self):         self.init()  # enable inspection tool         return true   class auiframe(wx.frame):     def __init__(self, *args, **kwargs):         super().__init__(size=(800, 800), *args, **kwargs)         self.setminsize((600, 600))          # create aui manager , tell manage frame         self._manager = aui.auimanager()         self._manager.setmanagedwindow(self)          inner_panel1 = wx.panel(parent=self)         inner_panel1.setbackgroundcolour('#999980')         inner_panel1.setminsize((100, 100))         inner_panel1_info = aui.auipaneinfo().name('inner_panel1').caption('inner panel 1').left().\             closebutton(true).maximizebutton(true).minimizebutton(true).show().floatable(true)          inner_panel2 = wx.panel(parent=self)         inner_panel2.setbackgroundcolour('#999990')         inner_panel2_info = aui.auipaneinfo().name('inner_panel2').caption('inner panel 2').left().row(1).\             show().floatable(false)          inner_panel3 = wx.panel(parent=self)         inner_panel3.setbackgroundcolour('#9999a0')         inner_panel3.setminsize((100, 100))         inner_panel3_info = aui.auipaneinfo().name('inner_panel3').caption('inner panel 3').centerpane()          self._manager.addpane(inner_panel1, inner_panel1_info)         self._manager.addpane(inner_panel2, inner_panel2_info)         self._manager.addpane(inner_panel3, inner_panel3_info)         self._manager.update()      def __onquit(self, event):         self.manager.uninit()         del self.manager         self.destroy()  if __name__ == '__main__':     app = appwinspection(0)     frame = auiframe(parent=none, title='aui manager test')     app.settopwindow(frame)     frame.show()     app.mainloop() 

Comments

Popular posts from this blog

javascript - DIV "hiding" when changing dropdown value -

Does Firefox offer AppleScript support to get URL of windows? -

android - How to install packaged app on Firefox for mobile? -