2

私はしばらくの間 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 パターンを実装することを学ぶことは、ここでの前進ですか?

ありがとう。

4

2 に答える 2

3

__init__別の引数としてgamePlayer オブジェクトを渡すことができます。

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

長期的には、これは理想的ではありません。

空のパネルの構築と、そのパネルにデータをロードすることを分離する必要があります。空のパネルは 1 つのことであり、モデルからのデータを入力することとは無関係です。

フレームにデータを入力するには、さまざまな表示ウィジェットを更新するために使用される gamePlayer オブジェクトを指定する必要があります。

これに関するガイダンスについては、Document-View フレームワークを参照することをお勧めします。 http://docs.wxwidgets.org/stable/wx_docviewoverview.html#docviewoverview。残念ながら、これに関する適切な Python の例は存在しないため、C++ コードから Python への変換は混乱を招く可能性があります。

最終的に、表示されているメイン オブジェクト (「gamePlayer」) である「ドキュメント」が作成されます。各フレームは、そのドキュメントのビューです。

于 2008-12-24T19:42:02.257 に答える
1

Model-View-Controller (MVC) フレームワークを使用すると、共通データ (モデル) にアクセスし、コントローラーを介して GUI (ビュー) に表示できます。良い説明がここにあります:

wxPython の MVC フレームワーク

基本的に、モデルがビューと直接やり取りできないようにすることで、複雑な混乱を回避できますが、変更を行ったことをコントローラーに投稿する必要はありません。その後、コントローラーはビューを適切に更新します。同様に、GUI のコントロールからモデルを更新します。このように、モデルとビュー コードは独立しており、それぞれの API にアクセスするコントローラー コードと結び付けられています。

于 2013-12-02T17:42:28.160 に答える