Reputation: 1651
I am designing a GUI with several components and two wx.Frame objects F1 and F2. F1 is the main frame and F2 is the secondary frame. I would like to have a mechanism, so the user can attach these two frames into one frame, and also detach them into two frames again if needed.
Assume F1 and F2 contain panels P1 and P2 respectively. When detached, the use should be able to move and resize each frame independently, and closing F1 will close the entire GUI. When attached, F1 will contain both P1 and P2 vertically and F2 will seem to vanish and become a part of F1. There is a lot of wiring and events and messages passed between P1 and P2 which should work in both attached and detached modes.
I have seen this effect in some modern GUI's, but I was unable to find a proper technique online to carry this out. What is a proper way to do this?
Thanks
Upvotes: 2
Views: 950
Reputation: 1651
There is a library in wxPython called AUI. It provides the mechanism to detach a panel from a frame. The following link has an example along with some other information:
http://wiki.wxpython.org/AuiNotebook%20(AGW)
Upvotes: 0
Reputation: 1651
I came up with a solution for this using the pubsub module. Following is a little example I wrote to show how it is done:
import wx
import gettext
from wx.lib.pubsub import pub
class SubFramePanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, wx.ID_ANY)
self.attachDetachButton = wx.Button(self, wx.ID_ANY, _("Attach"))
self.sayHelloButton = wx.Button(self, wx.ID_ANY, _("Say Hello"))
subPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
subPanelSizer.Add(self.attachDetachButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL, 0)
subPanelSizer.Add(self.sayHelloButton, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL, 0)
self.SetSizer(subPanelSizer)
self.attachDetachButton.Bind(wx.EVT_BUTTON, self.OnAttachDetachButton)
self.sayHelloButton.Bind(wx.EVT_BUTTON, self.OnSayHelloButton)
def OnAttachDetachButton(self, event):
if self.attachDetachButton.GetLabel() == "Attach":
self.attachDetachButton.SetLabel("Detach")
pub.sendMessage("show.mainframe.OnAttach", data=self)
else:
self.attachDetachButton.SetLabel("Attach")
pub.sendMessage("show.mainframe.OnDetach", data=self)
event.Skip()
def OnSayHelloButton(self, event):
pub.sendMessage("show.mainframe.addText", data="Say Hello\n")
event.Skip()
class SubFrame(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = wx.DEFAULT_FRAME_STYLE
if kwds.has_key("panel"):
self.panel = kwds["panel"]
del kwds["panel"]
else:
self.panel = None
wx.Frame.__init__(self, *args, **kwds)
if self.panel is None:
self.panel = SubFramePanel(self)
else:
self.panel.Reparent(self)
self.SetTitle(_("Sub Frame"))
self.SetSize((291, 93))
subFrameSizer = wx.BoxSizer(wx.VERTICAL)
subFrameSizer.Add(self.panel, 1, wx.EXPAND | wx.LEFT, 5)
self.SetSizer(subFrameSizer)
self.Layout()
pub.subscribe(self.OnClose, "show.subframe.OnClose")
def OnClose(self, data=None):
self.Close()
# end of class SubFrame
class MainFrame(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.text_ctrl_1 = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE)
pub.subscribe(self.OnAddText, "show.mainframe.addText")
pub.subscribe(self.OnAttach, "show.mainframe.OnAttach")
pub.subscribe(self.OnDetach, "show.mainframe.OnDetach")
self.SetTitle(_("Main Frame"))
self.SetSize((492, 271))
self.mainFrameSizer = wx.BoxSizer(wx.VERTICAL)
self.mainFrameSizer.Add(self.text_ctrl_1, 1, wx.ALL | wx.EXPAND, 5)
self.SetSizer(self.mainFrameSizer)
self.Layout()
def OnAddText(self, data):
self.text_ctrl_1.WriteText(data)
def OnAttach(self, data):
self.mainFrameSizer.Add(data, 0, wx.ALL | wx.EXPAND, 5)
data.Reparent(self)
self.Layout()
pub.sendMessage("show.subframe.OnClose")
def OnDetach(self, data):
subFrame = SubFrame(self, wx.ID_ANY, "", panel=data)
self.mainFrameSizer.Remove(data)
self.Layout()
subFrame.Show()
class MyApp(wx.App):
def OnInit(self):
mainFrame = MainFrame(None, wx.ID_ANY, "")
self.SetTopWindow(mainFrame)
mainFrame.Show()
subFrame = SubFrame(mainFrame, wx.ID_ANY, "")
subFrame.Show()
return 1
if __name__ == "__main__":
gettext.install("app")
app = MyApp(0)
app.MainLoop()
Upvotes: 2
Reputation: 13882
I'm not sure you can move a wxPanel
from a wxFrame
to another on the fly on wx.
The main reason is that the panel is dependent of its parent and you can't change it on the fly.
Now if you really want to do it, you'll have to create copy the panel in the other frame and delete the previous panel and frame (or just hide them).
There's no built in copy but you can find a way to get the content of your original panel and copy it on the other one.
Upvotes: 0