我已经使用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模式吗?
感谢。
答案 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(视图)中显示它。这里有一个很好的解释:
基本上,你可以通过不允许模型直接与视图对话来避免纠结混乱,而是向控制器发布它已经进行了更改。然后控制器适当地更新视图。同样,从你gui的控件更新模型。这样,模型和视图代码是独立的,它们与访问每个API的控制器代码捆绑在一起。