我正在设计一个包含多个组件和两个wx.Frame对象F1和F2的GUI。 F1是主框架,F2是辅助框架。我想有一个机制,因此用户可以将这两个帧连接到一个帧中,并在需要时再将它们分成两个帧。
假设F1和F2分别包含面板P1和P2。分离时,使用应能够独立移动和调整每个帧的大小,关闭F1将关闭整个GUI。当连接时,F1将垂直包含P1和P2,F2似乎会消失并成为F1的一部分。在P1和P2之间传递了大量的接线和事件以及消息,它们应该在连接和分离模式下工作。
我在一些现代的GUI中看到了这种效果,但我无法在网上找到合适的技术来实现这一点。什么是正确的方法?
由于
答案 0 :(得分:1)
我使用pubsub模块为此想出了一个解决方案。以下是我写的一个小例子来说明它是如何完成的:
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()
答案 1 :(得分:0)
我不确定您是否可以在wx上随时将wxPanel
从wxFrame
移动到另一个{{1}}。
主要原因是面板依赖于其父级,您无法动态更改它。
现在,如果您真的想要这样做,则必须在另一帧中创建复制面板并删除前一个面板和框架(或者只是隐藏它们)。
没有内置副本,但您可以找到获取原始面板内容并将其复制到另一个上面的方法。
答案 2 :(得分:0)
wxPython中有一个名为AUI的库。它提供了从面板上拆下面板的机制。以下链接有一个示例以及其他一些信息: