2008-12-24 52 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的控制器代码绑定在一起。