2

プログラムでwxPythonのアクセラレーターのテーブルをループで作成してバインドしようとしているので、各アクセラレーターに新しいIDを取得して割り当てることを心配する必要はありません(外部リソースからハンドラーリストを吸い込むことを目的として、それらをハードコーディングするのではなく)。また、ハンドラーの多くは同じですが、パラメーター(移動、ズームなど)が異なるため、ラムダを介してハンドラーにいくつかの引数を渡します。

このクラスはwx.Frameからサブクラスsetup_accelerators()化され、初期化中に呼び出されます。

def setup_accelerators(self):

    bindings = [
                  (wx.ACCEL_CTRL,  wx.WXK_UP, self.on_move, 'up'),
                  (wx.ACCEL_CTRL,  wx.WXK_DOWN, self.on_move, 'down'),
                  (wx.ACCEL_CTRL,  wx.WXK_LEFT, self.on_move, 'left'),
                  (wx.ACCEL_CTRL,  wx.WXK_RIGHT, self.on_move, 'right'),
                  ]


    accelEntries = []

    for binding in bindings:
        eventId = wx.NewId()
        accelEntries.append( (binding[0], binding[1], eventId) )

        self.Bind(wx.EVT_MENU, lambda event: binding[2](event, binding[3]), id=eventId)


    accelTable = wx.AcceleratorTable(accelEntries)
    self.SetAcceleratorTable(accelTable)

def on_move(self, e, direction):
    print direction

ただし、これはすべてのアクセラレータを最後のエントリにバインドしているように見えるため、他の3つすべてと同様に、Ctrl+Upが出力されます。"right"この方法で複数のハンドラーを正しくバインドするにはどうすればよいですか?

4

1 に答える 1

3

とった。問題は、ラムダへの引数として自分の方向を渡していないことでした(ラムダが受け入れとして定義されたのはそれだけだったので、イベント引数(および自己)だけを見ていました) このページは私に必要な助けを与えてくれましたこれを機能させる(ここに要点があります):

import wx

class MyForm(wx.Frame):

    #----------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Programmatic binding of accelerators in wxPython", size=(450,150))

        # Add a panel so it looks the correct on all platforms
        panel = wx.Panel(self, wx.ID_ANY)
        bindings = [
                  (wx.ACCEL_CTRL,  wx.WXK_UP, 'up'),
                  (wx.ACCEL_CTRL,  wx.WXK_DOWN, 'down'),
                  (wx.ACCEL_CTRL,  wx.WXK_LEFT, 'left'),
                  (wx.ACCEL_CTRL,  wx.WXK_RIGHT, 'right'),
                  ]


        accelEntries = []

        for binding in bindings:
            eventId = wx.NewId()
            accelEntries.append( (binding[0], binding[1], eventId) )

            self.Bind(wx.EVT_MENU, lambda evt, temp=binding[2]: self.on_move(evt, temp), id=eventId)

        accelTable  = wx.AcceleratorTable(accelEntries)
        self.SetAcceleratorTable(accelTable )
     #----------------------------------------------------------------------

    def on_move(self, Event, direction):
        print "You pressed CTRL+"+direction

# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()

私の最初の答え(これは許容できる代替ソリューションです)は次のとおりです。

import wx

class MyForm(wx.Frame):

    #----------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial", size=(500,500))

        # Add a panel so it looks the correct on all platforms
        panel = wx.Panel(self, wx.ID_ANY)
        bindings = [
                  (wx.ACCEL_CTRL,  wx.WXK_UP, self.on_move_up),
                  (wx.ACCEL_CTRL,  wx.WXK_DOWN, self.on_move_down),
                  (wx.ACCEL_CTRL,  wx.WXK_LEFT, self.on_move_left),
                  (wx.ACCEL_CTRL,  wx.WXK_RIGHT, self.on_move_right),
                  ]


        accelEntries = []

        for binding in bindings:
            eventId = wx.NewId()
            accelEntries.append( (binding[0], binding[1], eventId) )

            self.Bind(wx.EVT_MENU, binding[2], id=eventId)

        accelTable  = wx.AcceleratorTable(accelEntries)
        self.SetAcceleratorTable(accelTable )
     #----------------------------------------------------------------------
    def on_move_up(self, event):
        print "You pressed CTRL+up"
    def on_move_down(self, event):
        print "You pressed CTRL+down"
    def on_move_left(self, event):
        print "You pressed CTRL+left"
    def on_move_right(self, event):
        print "You pressed CTRL+right"

# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()
于 2012-10-17T22:57:43.903 に答える