Я уже некоторое время работаю с 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 как глобальный объект, но это обычно не одобряется - есть ли лучший способ сделать это?
Есть метод передачи объектов в привязках событий в этот вопрос, но он кажется не совсем правильным.
Есть ли здесь возможность научиться реализовывать шаблон MVC?
Спасибо.






Вы можете передать объект 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»). Каждый фрейм - это представление этого документа.
Фреймворк модель-представление-контроллер (MVC) позволяет вам получать доступ к общим данным (модели) и отображать их в графическом интерфейсе пользователя (представления) через контроллер. Здесь можно найти хорошее объяснение:
По сути, вы избегаете путаницы, не позволяя модели напрямую взаимодействовать с представлениями, а скорее отправляя контроллеру информацию о внесенных изменениях. Затем контроллер обновляет представления соответствующим образом. То же самое для обновления модели из элементов управления на вашем графическом интерфейсе. Таким образом, модель и код представления независимы и связаны вместе с кодом контроллера, который обращается к API каждого из них.