2009-06-10 2 views
4

次のコード(thisの影響を受けています)では、単一のイベントハンドラbuttonClickを使用してウィンドウのタイトルを変更します。現在、イベントのIDがボタンのIDに対応するかどうかを評価する必要があります。 2つではなく50のボタンを追加することに決めたら、この方法は煩雑になる可能性があります。これを行うより良い方法はありますか?イベントを呼び出したボタンの名前を取得する最も良い方法は?

import wx 

class MyFrame(wx.Frame): 
    def __init__(self): 
     wx.Frame.__init__(self, None, wx.ID_ANY, 'wxBitmapButton', 
      pos=(300, 150), size=(300, 350)) 
     self.panel1 = wx.Panel(self, -1) 

     self.button1 = wx.Button(self.panel1, id=-1, 
      pos=(10, 20), size = (20,20)) 
     self.button1.Bind(wx.EVT_BUTTON, self.buttonClick) 

     self.button2 = wx.Button(self.panel1, id=-1, 
      pos=(40, 20), size = (20,20)) 
     self.button2.Bind(wx.EVT_BUTTON, self.buttonClick) 

     self.Show(True) 

    def buttonClick(self,event): 
     if event.Id == self.button1.Id: 
      self.SetTitle("Button 1 clicked") 
     elif event.Id == self.button2.Id: 
      self.SetTitle("Button 2 clicked")    

application = wx.PySimpleApp() 
window = MyFrame() 
application.MainLoop() 

答えて

9

あなたがボタンに名前を付け、その後、イベントハンドラ内の名前で見ることができます。

ボタンをクリックすると、あなたがボタン

b = wx.Button(self, 10, "Default Button", (20, 20)) 
b.myname = "default button" 
self.Bind(wx.EVT_BUTTON, self.OnClick, b) 

を作るとき:

def OnClick(self, event): 
    name = event.GetEventObject().myname 
+0

をStackOverflowのために私の最初の投稿です。 – FogleBird

3

長いif/elifのボタンとボタン名または何である値の.Idあるキーでdict、その代わりに、あなたはbuttonClickに単一dict検索を行う連鎖してください。

コードスニペット:__init__で、dictの作成と更新を追加します。50個のボタン(または何でも)のため

self.panel1 = wx.Panel(self, -1) 
self.thebuttons = dict() 

self.button1 = wx.Button(self.panel1, id=-1, 
    pos=(10, 20), size = (20,20)) 
self.thebuttons[self.button1.Id] = 'Button 1' 
self.button1.Bind(wx.EVT_BUTTON, self.buttonClick) 

などを[彼らはより良い;-)ところで、ループ内に作成される可能性があります] 。 だからbuttonClickは次のようになります。

def buttonClick(self,event): 
     button_name = self.thebuttons.get(event.Id, '?No button?') 
     self.setTitle(button_name + ' clicked') 
1

あなたはボタンの辞書を作成し、idに基づいて外観を行うことができます...このような何か:

class MyFrame(wx.Frame): 
    def _add_button (self, *args): 
     btn = wx.Button (*args) 
     btn.Bind (wx.EVT_BUTTON, self.buttonClick) 
     self.buttons[btn.id] = btn 
    def __init__ (self): 
     self.button = dict() 
     self._add_button (self.panel1, id=-1, 
     pos=(10, 20), size = (20,20)) 

    self._add_button = (self.panel1, id=-1, 
     pos=(40, 20), size = (20,20)) 

    self.Show (True) 

    def buttonClick(self,event): 
     self.SetTitle (self.buttons[event.Id].label) 
0

私は同様の問題に遭遇した:Iユーザー提供のデータに基づいてボタンを生成していました。別のクラスに影響するボタンが必要でしたので、buttonclickに関する情報を渡す必要がありました。私が行ったことは、生成した各ボタンにボタンIDを明示的に割り当て、後でルックアップするために辞書に関する情報を保存していたことです。

これを行うにはもっときれいな方法があると思っていましたが、より多くの情報を渡すカスタムイベントを作成しましたが、私が見たのは辞書検索方法です。また、私はボタンのリストの周りを維持するので、私はそれらのすべてを必要なときに消去することができます。ここで

は似たようなの少しスクラブのサンプルコードです:

self.buttonDefs = {} 
self.buttons = [] 
id_increment = 800 
if (row, col) in self.items: 
    for ev in self.items[(row, col)]: 
     id_increment += 1 
     #### Populate a dict with the event information 
     self.buttonDefs[id_increment ] = (row, col, ev['user']) 
     #### 
     tempBtn = wx.Button(self.sidebar, id_increment , "Choose", 
          (0,50+len(self.buttons)*40), (50,20)) 
     self.sidebar.Bind(wx.EVT_BUTTON, self.OnShiftClick, tempBtn) 
     self.buttons.append(tempBtn) 

def OnShiftClick(self, evt): 
    ### Lookup the information from the dict 
    row, col, user = self.buttonDefs[evt.GetId()] 
    self.WriteToCell(row, col, user) 
    self.DrawShiftPicker(row, col) 
7

を、私はあなたが各ボタンからのイベントを処理するために、さまざまなイベントハンドラを使用することをお勧めします。

def goingTo(self, where): 
    def goingToHandler(event): 
     self.SetTitle("I'm going to " + where) 
    return goingToHandler 

def __init__(self): 
    buttonA.Bind(wx.EVT_BUTTON, self.goingTo("work")) 
    # clicking will say "I'm going to work" 
    buttonB.Bind(wx.EVT_BUTTON, self.goingTo("home")) 
    # clicking will say "I'm going to home" 
+0

うわー、私はそれが辞書検索方法よりもはるかに良い方法だと思います。この方法では、おそらく1つのエントリだけを使用しようとしているときに 'dict'を設定していません。 – pbh101

7

あなたはPythonのような言語で何ができるかを利用してください:共通の多くがある場合、あなたは、たとえば、たい特定の動作による返品機能関数にそれを組み合わせることができます。イベントコールバック関数に余分な引数を渡すことができます。

import functools 

def __init__(self): 
    # ... 
    for i in range(10): 
     name = 'Button %d' % i 
     button = wx.Button(parent, -1, name) 
     func = functools.partial(self.on_button, name=name) 
     button.Bind(wx.EVT_BUTTON, func) 
    # ... 

def on_button(self, event, name): 
    print '%s clicked' % name 

もちろん、引数は任意の値にすることができます。

+1

素敵なアプローチとクールな新しいPython機能の使用(2.5は私にとっては新しいものです)。 'functools.partail'は確かにより明確で、厄介な名前の縛りの問題はありませんが、私はしばしばこれの' lambda'版をします。 – tom10

0

ボタンを押したままにするために同じことをする必要がありました。イベントにバインドするためにラムダ関数を使用しました。そうすれば、ボタンオブジェクト全体をイベントハンドラ関数に渡して、それに応じて操作することができます。

class PlatGridderTop(wx.Frame): 
     numbuttons = 0 
     buttonlist = [] 


     def create_another_button(self, event): # wxGlade: PlateGridderTop.<event_handler> 
       buttoncreator_id = wx.ID_ANY 
       butonname = "button" + str(buttoncreator_id) 
       PlateGridderTop.numbuttons = PlateGridderTop.numbuttons + 1 
       thisbutton_number = PlateGridderTop.numbuttons 

       self.buttonname = wx.Button(self,buttoncreator_id ,"ChildButton %s" % thisbutton_number) 
       self.Bind(wx.EVT_BUTTON,lambda event, buttonpressed=self.buttonname: self.print_button_press(event,buttonpressed),self.buttonname) 
       self.buttonlist.append(self.buttonname) 
       self.__do_layout() 
       print "Clicked plate button %s" % butonname 
       event.Skip() 
     def print_button_press(self,event,clickerbutton): 
       """Just a dummy method that responds to a button press""" 
       print "Clicked a created button named %s with wxpython ID %s" % (clickerbutton.GetLabel(),event.GetId()) 

免責事項:これは私がより良い方法を考えることができないとき、私は多くの場合、同様のウィジェットの属性を設定し

関連する問題