2013-05-10 20 views
1

我正在設計一個包含多個組件和兩個wx.Frame對象F1和F2的GUI。 F1是主框架,F2是次框架。我想有一個機制,所以用戶可以將這兩個框架附加到一個框架中,並且如果需要也可以將它們再次分離成兩個框架。在wxpython中附加/分離兩幀

假設F1和F2分別包含面板P1和P2。分離時,使用應能夠獨立移動和調整每個框架的大小,關閉F1將關閉整個GUI。當連接時,F1將垂直包含P1和P2,F2似乎消失併成爲F1的一部分。 P1和P2之間有很多接線,事件和消息傳遞,它們應該可以在連接和分離模式下工作。

我在一些現代GUI中看到了這種效果,但是我無法在網上找到適當的技術來執行此操作。什麼是正確的方法來做到這一點?

感謝

回答

0

我不知道,你可以從一個wxFrame上WX移動wxPanel到另一個上飛。

主要原因是面板依賴於其父項,並且無法實時更改。

現在,如果您真的想要這樣做,您必須在另一個框架中創建複製面板並刪除以前的面板和框架(或者只是隱藏它們)。

沒有內置副本,但您可以找到一種方法來獲取原始面板的內容並將其複製到另一個面板上。

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()