wxPython и совместное использование объектов между окнами - PullRequest
2 голосов
/ 24 декабря 2008

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

В этом вопросе есть метод передачи объектов в привязках событий *1009*, но он не совсем правильный.

Способствует ли здесь научиться внедрять шаблон MVC?

Спасибо.

Ответы [ 2 ]

3 голосов
/ 24 декабря 2008

Вы можете передать объект 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 голос
/ 02 декабря 2013

Каркас Model-View-Controller (MVC) позволяет вам получать доступ к общим данным (Model) и отображать их в вашем GUI (Views) через Controller. Хорошее объяснение находится здесь:

MVC Framework для wxPython

По сути, вы избегаете запутанных беспорядков, не позволяя модели напрямую взаимодействовать с представлениями, а скорее отправляете сообщения в контроллер, в котором были внесены изменения. Затем контроллер обновляет представления соответствующим образом. Аналогично для обновления модели из элементов управления на вашем графическом интерфейсе. Таким образом, модель и код представления независимы, и они связаны вместе с кодом контроллера, который обращается к API каждого из них.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...