2008-12-24 60 views
2

我一直在使用python一段時間,剛開始學習wxPython。創建幾個小程序後,我很難理解如何創建可在對話框之間共享的對象。wxPython和窗口間共享對象

下面是一些代碼爲例(道歉長度 - 我試圖微調):

import wx 

class ExampleFrame(wx.Frame): 
    """The main GUI""" 
    def __init__(self, parent, id, title): 
     wx.Frame.__init__(self, parent, id, title, size=(200,75)) 
     mainSizer = wx.BoxSizer(wx.VERTICAL) 

     # Setup buttons 
     buttonSizer = wx.BoxSizer(wx.HORIZONTAL) 
     playerButton = wx.Button(self, wx.ID_ANY, "Player number", wx.DefaultPosition, wx.DefaultSize, 0) 
     buttonSizer.Add(playerButton, 1, wx.ALL | wx.EXPAND, 0) 
     nameButton = wx.Button(self, wx.ID_ANY, "Player name", wx.DefaultPosition, wx.DefaultSize, 0) 
     buttonSizer.Add(nameButton, 1, wx.ALL | wx.EXPAND, 0) 

     # Complete layout and add statusbar 
     mainSizer.Add(buttonSizer, 1, wx.EXPAND, 5) 
     self.SetSizer(mainSizer) 
     self.Layout() 

     # Deal with the events 
     playerButton.Bind(wx.EVT_BUTTON, self.playerButtonEvent) 
     nameButton.Bind(wx.EVT_BUTTON, self.nameButtonEvent) 
     self.Show(True) 
     return 

    def playerButtonEvent(self, event): 
     """Displays the number of game players""" 
     playerDialog = PlayerDialogWindow(None, -1, "Player") 
     playerDialogResult = playerDialog.ShowModal() 
     playerDialog.Destroy() 
     return 

    def nameButtonEvent(self, event): 
     """Displays the names of game players""" 
     nameDialog = NameDialogWindow(None, -1, "Name") 
     nameDialogResult = nameDialog.ShowModal() 
     nameDialog.Destroy() 
     return 

class PlayerDialogWindow(wx.Dialog): 
    """Displays the player number""" 
    def __init__(self, parent, id, title): 
     wx.Dialog.__init__(self, parent, id, title, size=(200,120)) 

     # Setup layout items 
     self.SetAutoLayout(True) 
     mainSizer = wx.BoxSizer(wx.VERTICAL) 
     dialogPanel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL) 
     dialogSizer = wx.BoxSizer(wx.VERTICAL) 

     # Display player number 
     playerNumber = "Player number is %i" % gamePlayer.number 
     newLabel = wx.StaticText(dialogPanel, wx.ID_ANY, playerNumber, wx.DefaultPosition, wx.DefaultSize, 0) 
     dialogSizer.Add(newLabel, 0, wx.ALL | wx.EXPAND, 5) 

     # Setup buttons 
     buttonSizer = wx.StdDialogButtonSizer() 
     okButton = wx.Button(dialogPanel, wx.ID_OK) 
     buttonSizer.AddButton(okButton) 
     buttonSizer.Realize() 
     dialogSizer.Add(buttonSizer, 1, wx.EXPAND, 5) 

     # Complete layout 
     dialogPanel.SetSizer(dialogSizer) 
     dialogPanel.Layout() 
     dialogSizer.Fit(dialogPanel) 
     mainSizer.Add(dialogPanel, 1, wx.ALL | wx.EXPAND, 5) 
     self.SetSizer(mainSizer) 
     self.Layout() 

     # Deal with the button events 
     okButton.Bind(wx.EVT_BUTTON, self.okClick) 
     return 

    def okClick(self, event): 
     """Deals with the user clicking the ok button""" 
     self.EndModal(wx.ID_OK) 
     return 

class NameDialogWindow(wx.Dialog): 
    """Displays the player name""" 
    def __init__(self, parent, id, title): 
     wx.Dialog.__init__(self, parent, id, title, size=(200,120)) 

     # Setup layout items 
     self.SetAutoLayout(True) 
     mainSizer = wx.BoxSizer(wx.VERTICAL) 
     dialogPanel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL) 
     dialogSizer = wx.BoxSizer(wx.VERTICAL) 

     # Display player number 
     playerNumber = "Player name is %s" % gamePlayer.name 
     newLabel = wx.StaticText(dialogPanel, wx.ID_ANY, playerNumber, wx.DefaultPosition, wx.DefaultSize, 0) 
     dialogSizer.Add(newLabel, 0, wx.ALL | wx.EXPAND, 5) 

     # Setup buttons 
     buttonSizer = wx.StdDialogButtonSizer() 
     okButton = wx.Button(dialogPanel, wx.ID_OK) 
     buttonSizer.AddButton(okButton) 
     buttonSizer.Realize() 
     dialogSizer.Add(buttonSizer, 1, wx.EXPAND, 5) 

     # Complete layout 
     dialogPanel.SetSizer(dialogSizer) 
     dialogPanel.Layout() 
     dialogSizer.Fit(dialogPanel) 
     mainSizer.Add(dialogPanel, 1, wx.ALL | wx.EXPAND, 5) 
     self.SetSizer(mainSizer) 
     self.Layout() 

     # Deal with the button events 
     okButton.Bind(wx.EVT_BUTTON, self.okClick) 
     return 

    def okClick(self, event): 
     """Deals with the user clicking the ok button""" 
     self.EndModal(wx.ID_OK) 
     return 

class Player(object): 
    """A game player""" 
    def __init__(self, number, name): 
     self.number = number 
     self.name = name 
     return 

def main(): 
    # Start GUI 
    global gamePlayer 
    gamePlayer = Player(1, "John Smith") 
    app = wx.App(redirect=False) 
    frame = ExampleFrame(None, -1, "Example frame") 
    frame.Show(True) 
    app.MainLoop() 
    return 0 

if __name__ == '__main__': 
    main() 

所以,我想這兩個對話框訪問的遊戲玩家對象。目前,我能想到的唯一方法就是將gamePlayer對象創建爲全局對象,但這些對象通常都會被忽略 - 有沒有更好的方法來做到這一點?

this question中有一種在事件綁定中傳遞對象的方法,但它感覺不太正確。

正在學習如何在這裏實現MVC模式?

謝謝。

回答

3

您可以將gamePlayer對象作爲另一個參數傳遞給__init__

def __init__(self, parent, id, title, gamePlayer): 
    ...etc... 

從長遠來看,這並不理想。

您應該分開構建一個空面板以加載包含數據的面板。空板是一回事,用來自模型的數據填充它是無關緊要的。

使用數據填充一個框架就是必須給予gamePlayer對象的地方,它將用於更新各種顯示小部件。

我建議你看看文檔視圖框架的指導。 http://docs.wxwidgets.org/stable/wx_docviewoverview.html#docviewoverview。不幸的是,這裏沒有任何好的Python例子,所以將C++代碼轉換爲Python可能會令人困惑。

最終,您有一個「文檔」,它是顯示的主要對象(「gamePlayer」)。每個框架都是該文檔的視圖。

1

模型 - 視圖 - 控制器(MVC)框架允許您訪問公共數據(模型)並通過控制器將其顯示在GUI(視圖)中。通過不允許模型直接對話的意見,而是張貼到,它已經進行了更改控制器

MVC Framework for wxPython

基本上,你避免混亂糾結:一個很好的解釋可以在這裏找到。控制器然後適當地更新視圖。同樣更新來自gui控件的模型。這樣模型和視圖代碼是獨立的,並且它們與訪問每個API的控制器代碼綁定在一起。