Panes closed by AuiManager are always docked
Riccardo Borgani <[email protected]> Thu, 12 Apr 2018 00:59:58 -0700 (PDT)
| Newsgroups | gmane.comp.python.wxpython.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi all,
I have an application where multiple panes are managed by
wx.lib.agw.aui.AuiManager. Some of them are usually docked and some are
floating.
If a floating pane is closed, next time I open it I would like it to be
still floating. Instead, it always appears docked.
Looking at the method AuiManager.ClosePane in
wx/lib/agw/aui/framemanager.py:
https://github.com/wxWidgets/Phoenix/blob/wxPython-4.0.1/wx/lib/agw/aui/framemanager.py#L5068
pane_info.Dock().Hide()
The pane is always docked before being hidden.
Is this a bug, or is there a reason for this behavior?
To fix/avoid this behavior, I bind to EVT_AUI_PANE_CLOSE and hide the pane
myself:
def OnAuiPaneClose(self, evt):
pane = evt.GetPane()
if not pane.IsDestroyOnClose():
pane.Hide()
self._mgr.Update()
evt.Veto()
Next time I open the pane it is indeed floating, but now the title bar and
the close button are gone! Which means I can't move or close the pane
again...
Why is this happening?
See attached script and screenshots for a demonstration of this behavior.
You can open two panes from the View menu.
Pane 1 is left to AuiManager. So if you open it, close it, and open it
again it will be docked.
Pane 2 is hidden by OnAuiPaneClose and its event vetoed. So if you open it,
close it, and open it again it will be floating but the title bar will be
gone.
I've tested this with Python 2.7.14 and wxpython 4.0.1 (from the anaconda
repository).
On Ubuntu 16.04 and 17.10, and Windows 10 I got the same behavior.
On macOS 10.13 High Sierra, instead, it works fine (the title bar doesn't
disappear).
An alternative I can think of is to make my own AuiManager which lets
ClosePane do its work, and then sets the pane floating again afterwards.
import wx.lib.agw.aui as aui
class MyAuiManager(aui.AuiManager):
def ClosePane(self, pane_info):
was_floating = False
if not pane_info.IsDestroyOnClose():
if pane_info.IsFloating():
was_floating = True
super(MyAuiManager, self).ClosePane(pane_info)
if was_floating:
pane_info.Float()
This seems to work fine. Is there some reason for not doing it?
Thanks for your help, and for the good work!
Riccardo
--
You received this message because you are subscribed to the Google Groups "wxPython-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.
test_aui.py
(text/x-python, 3.9 KB)
"""
This script will open an empty frame managed by AuiManager.
From the View menu you can open two panes: Pane 1 and Pane 2.
The first time you open the panes, they will both be floating.
The second time you open the panes (after closing them):
- Pane 1 will be docked to the left;
- Pane 2 will be floating, but the title bar and the close button
will be gone!
The difference is in how OnAuiPaneClose treats the two panes:
- Pane 1 is ignored so AuiManager will handle it as usual,
it will first dock it and then hide it
(see method AuiManager.ClosePane in wx/lib/agw/aui/framemanager.py)
- Pane 2 will be hidden and the related event vetoed.
"""
import wx
import wx.lib.agw.aui as aui
ID_Show1 = wx.NewId()
ID_Show2 = wx.NewId()
class MyGui(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent=None, title="Test Frame")
self._mgr = aui.AuiManager()
self._mgr.SetManagedWindow(self)
# create menu
mb = wx.MenuBar()
view_menu = wx.Menu()
view_menu.Append(ID_Show1, "Show Pane 1")
view_menu.Append(ID_Show2, "Show Pane 2")
mb.Append(view_menu, "View")
self.SetMenuBar(mb)
self.SetMinSize(wx.Size(400, 300))
self.Bind(wx.EVT_MENU, self.OnShow1, id=ID_Show1)
self.Bind(wx.EVT_MENU, self.OnShow2, id=ID_Show2)
self.Bind(wx.EVT_CLOSE, self.OnClose)
# Treat closing of Pane 1 and Pane 2 differently
self.Bind(aui.EVT_AUI_PANE_CLOSE, self.OnAuiPaneClose)
self.Create1()
self.Create2()
for pane in self._mgr.GetAllPanes():
pane.Hide()
self._mgr.Update()
def OnAuiPaneClose(self, evt):
""" Don't let AuiManager close Pane 2, instead we hide it ourselves.
Ignore Pane 1 (let AuiManager do its thing).
"""
pane = evt.GetPane()
if pane.caption == "Pane 2":
pane.Hide()
self._mgr.Update()
evt.Veto()
def Create1(self):
self.panel1 = wx.Panel(self)
szr = wx.BoxSizer(wx.VERTICAL)
szr.Add(wx.StaticText(self.panel1, label="Panel 1"))
szr.Add(wx.StaticText(self.panel1, label="OnAuiPaneClose:"))
szr.Add(wx.StaticText(self.panel1, label="do nothing"))
szr.Add(wx.StaticText(self.panel1, label="let AuiManager work"))
self.panel1.SetSizerAndFit(szr)
self._mgr.AddPane(self.panel1, aui.AuiPaneInfo().
Caption("Pane 1").
Float().
FloatingSize(wx.Size(150, 100)).
CloseButton(True).
MaximizeButton(True))
def Create2(self):
self.panel2 = wx.Panel(self)
szr = wx.BoxSizer(wx.VERTICAL)
szr.Add(wx.StaticText(self.panel2, label="Panel 2"))
szr.Add(wx.StaticText(self.panel2, label="OnAuiPaneClose:"))
szr.Add(wx.StaticText(self.panel2, label="pane will be hidden"))
szr.Add(wx.StaticText(self.panel2, label="event will be vetoed"))
self.panel2.SetSizerAndFit(szr)
self._mgr.AddPane(self.panel2, aui.AuiPaneInfo().
Caption("Pane 2").
Float().
FloatingSize(wx.Size(150, 100)).
CloseButton(True).
MaximizeButton(True))
def OnShow1(self, event):
pane = self._mgr.GetPane(self.panel1)
if pane.IsShown():
pane.Hide()
else:
pane.Show()
self._mgr.Update()
def OnShow2(self, event):
pane = self._mgr.GetPane(self.panel2)
if pane.IsShown():
pane.Hide()
else:
pane.Show()
self._mgr.Update()
def OnClose(self, event):
self._mgr.UnInit()
del self._mgr
self.Destroy()
if __name__ == '__main__':
myapp = wx.App(redirect=False)
mygui = MyGui()
mygui.Show(True)
myapp.MainLoop()
before.png
(image/png, 71 KB) - not displayed
after.png
(image/png, 81.7 KB) - not displayed