wxPython并在窗口之间共享对象

时间:2008-12-24 19:30:02

标签: python wxpython

我已经使用python一段时间了,我刚刚开始学习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对象。目前,我能想到的唯一方法就是将gamePlayer对象创建为全局对象,但这些通常不赞成 - 有更好的方法吗?

this question中有一种在事件绑定中传递对象的方法,但它感觉不太正确。

学习如何在这里实现MVC模式吗?

感谢。

2 个答案:

答案 0 :(得分:3)

您可以将gamePlayer对象作为另一个参数传递给__init__

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

从长远来看,这并不理想。

您应该将构建一个空面板与将该面板加载数据分开。空面板是一回事,用模型中的数据填充它是不相关的。

使用数据填充框架是必须获得gamePlayer对象的位置,该对象将用于更新各种显示小部件。

我建议您查看Document-View框架以获取相关指导。 http://docs.wxwidgets.org/stable/wx_docviewoverview.html#docviewoverview。不幸的是,没有任何好的Python示例,因此将C ++代码转换为Python会让人感到困惑。

最终,你有一个“文档”,它是正在显示的主要对象(“gamePlayer”)。每个框架都是该文档的视图。

答案 1 :(得分:1)

模型 - 视图 - 控制器(MVC)框架允许您访问公共数据(模型)并通过Controller在GUI(视图)中显示它。这里有一个很好的解释:

MVC Framework for wxPython

基本上,你可以通过不允许模型直接与视图对话来避免纠结混乱,而是向控制器发布它已经进行了更改。然后控制器适当地更新视图。同样,从你gui的控件更新模型。这样,模型和视图代码是独立的,它们与访问每个API的控制器代码捆绑在一起。